diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 6b449ef..c3dc419 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -11,7 +11,9 @@ builds: - linux goarch: - amd64 - + env: + - CGO_ENABLED=0 + - CC=gcc ldflags: - -s -w -X main.version={{.Tag}} -X main.commitHash={{.ShortCommit}} diff --git a/CHANGELOG.md b/CHANGELOG.md index a8ba01f..f2fceeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,32 @@ and this project adheres to [Semantic Versioning]https://semver.org/spec/v2.0.0. ### Unreleased +### [0.9.8] - 2025-11-17 + +- fix: disable CGO support in goreleaser configuration +- fix: bug in banwidth delegation accounting +- fix: fixed evm incorrectly assigning gas fee tip +- fix: adjust total gas price calculation to remove gas tip cap addition +- fix: correct total gas price calculation to exclude gas tip cap +- fix: remove gas tip cap from total gas price calculation +- fix: fixed bug with secp256k1 curve in cgo disabled env +- fix: update gas estimation logic and add gas limit function for block +- fix: bandwidth estimate for tron transfer +- fix: evm estimate for transfer +- init e2e tests + +### [0.9.7] - 2025-10-15 + +- Added support for disabled CGO_ENABLED flag in EVM, TRON cryptography [DV-3641] + ### [0.9.6] - 2025-09-29 + - Added two-factor secret encryption [DV-2526] - Add support events status for internal transactions [DV-3436] - fix code rpc wrapping [DV-3461] ### [0.9.5] - 2025-09-15 + - Add memory buffer for processing logs [DV-3361] - Add dockerfile [DV-3387] diff --git a/go.mod b/go.mod index e820f46..b5f3cf9 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.5-0.20250213152832-bb52d7d78d9c github.com/btcsuite/btcd/btcutil v1.1.7-0.20250213152832-bb52d7d78d9c github.com/btcsuite/btcd/chaincfg/chainhash v1.1.1-0.20250213152832-bb52d7d78d9c - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/ethereum/go-ethereum v1.15.8 github.com/fbsobreira/gotron-sdk v0.0.0-20250427130616-96b87f5d2100 github.com/go-playground/validator/v10 v10.26.0 diff --git a/internal/fsm/fsmevm/fsm_helpers.go b/internal/fsm/fsmevm/fsm_helpers.go index 47c2630..f02cb1e 100644 --- a/internal/fsm/fsmevm/fsm_helpers.go +++ b/internal/fsm/fsmevm/fsm_helpers.go @@ -2,6 +2,7 @@ package fsmevm import ( "context" + "crypto/ecdsa" "fmt" "math/big" "strings" @@ -11,7 +12,6 @@ import ( "github.com/dv-net/dv-processing/internal/store/repos/repo_transfer_transactions" trxv2 "github.com/dv-net/dv-proto/gen/go/eproxy/transactions/v2" - "github.com/btcsuite/btcd/btcec/v2" "github.com/dv-net/dv-processing/internal/constants" "github.com/dv-net/dv-processing/internal/services/webhooks" "github.com/dv-net/dv-processing/internal/store/repos" @@ -20,7 +20,6 @@ import ( "github.com/dv-net/dv-processing/pkg/utils" "github.com/dv-net/dv-processing/pkg/walletsdk/evm" "github.com/dv-net/dv-processing/pkg/walletsdk/evm/erc20" - "github.com/dv-net/dv-processing/pkg/walletsdk/wconstants" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -202,8 +201,8 @@ func (s *FSM) getAssetDecimals(ctx context.Context, assetIdentifier string) (int type walletCreds struct { Address string - PrivateKey *btcec.PrivateKey - PublicKey *btcec.PublicKey + PrivateKey *ecdsa.PrivateKey + PublicKey *ecdsa.PublicKey } // getWalletCreds @@ -260,7 +259,7 @@ func (s *FSM) sendBaseAsset(ctx context.Context, wCreds *walletCreds, toAddress return nil, nil, err } - gasLimit := gasLimitByBlockchain(s.evm.Blockchain()) + gasLimit := evm.GasLimitByBlockchain(s.evm.Blockchain()) s.logger.Infow( s.stringForBaseAsset("sending %s"), @@ -288,7 +287,7 @@ func (s *FSM) sendBaseAsset(ctx context.Context, wCreds *walletCreds, toAddress Data: nil, }) - signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(chainID), wCreds.PrivateKey.ToECDSA()) + signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(chainID), wCreds.PrivateKey) if err != nil { return nil, nil, fmt.Errorf("sign transaction: %w", err) } @@ -346,7 +345,7 @@ func (s *FSM) sendERC20(ctx context.Context, wCreds *walletCreds, contractAddres } // create auth - auth, err := bind.NewKeyedTransactorWithChainID(wCreds.PrivateKey.ToECDSA(), chainID) + auth, err := bind.NewKeyedTransactorWithChainID(wCreds.PrivateKey, chainID) if err != nil { return nil, nil, err } @@ -477,13 +476,3 @@ func (s *FSM) prepareTransferTransactionTypeByStep() (*models.TransferTransactio return nil, fmt.Errorf("unknown transfer step: %s", s.wf.CurrentStep().Name) } } - -// gasLimitByBlockchain returns the gas limit by blockchain. -func gasLimitByBlockchain(blockchain wconstants.BlockchainType) uint64 { - switch blockchain { - case wconstants.BlockchainTypeArbitrum: - return 38000 - default: - return 21000 // Default gas limit for unknown blockchains - } -} diff --git a/internal/fsm/fsmtron/fsm_helpers.go b/internal/fsm/fsmtron/fsm_helpers.go index b1089b9..ce08901 100644 --- a/internal/fsm/fsmtron/fsm_helpers.go +++ b/internal/fsm/fsmtron/fsm_helpers.go @@ -2,12 +2,12 @@ package fsmtron import ( "context" + "crypto/ecdsa" "fmt" "strings" "time" "connectrpc.com/connect" - "github.com/btcsuite/btcd/btcec/v2" trxv2 "github.com/dv-net/dv-proto/gen/go/eproxy/transactions/v2" "github.com/fbsobreira/gotron-sdk/pkg/common" "github.com/fbsobreira/gotron-sdk/pkg/proto/api" @@ -155,8 +155,8 @@ func (s *FSM) getAssetDecimals(ctx context.Context, assetIdentifier string) (int type walletCreds struct { Address string - PrivateKey *btcec.PrivateKey - PublicKey *btcec.PublicKey + PrivateKey *ecdsa.PrivateKey + PublicKey *ecdsa.PublicKey } // getWalletCreds @@ -201,7 +201,7 @@ func (s *FSM) systemActivation(ctx context.Context, wCreds *walletCreds, toAddre return nil, fmt.Errorf("create system activation tx error: %s", string(tx.Result.Message)) } - if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey.ToECDSA()); err != nil { + if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey); err != nil { return nil, fmt.Errorf("sign transaction: %w", err) } @@ -252,7 +252,7 @@ func (s *FSM) sendTRX(ctx context.Context, wCreds *walletCreds, toAddress string return nil, fmt.Errorf("create send trx tx error: %s", string(tx.Result.Message)) } - if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey.ToECDSA()); err != nil { + if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey); err != nil { return nil, fmt.Errorf("sign transaction: %w", err) } @@ -319,7 +319,7 @@ func (s *FSM) sendTrc20(ctx context.Context, wCreds *walletCreds, contractAddres return nil, fmt.Errorf("create send trc20 tx error: %s", string(tx.Result.Message)) } - if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey.ToECDSA()); err != nil { + if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey); err != nil { return nil, fmt.Errorf("sign transaction: %w", err) } @@ -407,7 +407,7 @@ func (s *FSM) delegateResource( return nil, nil, fmt.Errorf("create delegate tx error: %s", string(tx.Result.Message)) } - if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey.ToECDSA()); err != nil { + if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey); err != nil { return nil, nil, fmt.Errorf("sign transaction: %w", err) } @@ -464,7 +464,7 @@ func (s *FSM) reclaimResource(ctx context.Context, wCreds *walletCreds, toAddres return nil, nil, fmt.Errorf("create reclaim tx error: %s", string(tx.Result.Message)) } - if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey.ToECDSA()); err != nil { + if err := s.tron.SignTransaction(tx.GetTransaction(), wCreds.PrivateKey); err != nil { return nil, nil, fmt.Errorf("sign transaction: %w", err) } diff --git a/internal/fsm/fsmtron/stage_before.go b/internal/fsm/fsmtron/stage_before.go index 5c9dc78..8102be0 100644 --- a/internal/fsm/fsmtron/stage_before.go +++ b/internal/fsm/fsmtron/stage_before.go @@ -209,7 +209,7 @@ func (s *FSM) activateWalletResources(ctx context.Context, _ *workflow.Workflow, } // sign transaction - if err = s.tron.SignTransaction(tx.Transaction, wcreds.PrivateKey.ToECDSA()); err != nil { + if err = s.tron.SignTransaction(tx.Transaction, wcreds.PrivateKey); err != nil { return fmt.Errorf("sign activation transaction: %w", err) } diff --git a/pkg/walletsdk/evm/estimate.go b/pkg/walletsdk/evm/estimate.go index 1d54d1c..62d8b6d 100644 --- a/pkg/walletsdk/evm/estimate.go +++ b/pkg/walletsdk/evm/estimate.go @@ -22,53 +22,25 @@ type EstimateTransferResult struct { // EstimateTransfer estimates the transfer fee. Amount is in Eth func (s *EVM) EstimateTransfer(ctx context.Context, fromAddress, toAddress, assetIdentifier string, amount decimal.Decimal, decimals int64) (*EstimateTransferResult, error) { - var gasAmount decimal.Decimal - var gasTipCap decimal.Decimal - var totalFeeAmount decimal.Decimal - var totalGasPrice decimal.Decimal - estimate, err := s.EstimateFee(ctx) if err != nil { return nil, fmt.Errorf("failed to estimate fee: %w", err) } + var gasAmount decimal.Decimal if assetIdentifier == s.config.Blockchain.GetAssetIdentifier() { - estimatedGas, err := s.node.EstimateGas(ctx, ethereum.CallMsg{ - From: common.HexToAddress(fromAddress), - To: utils.Pointer(common.HexToAddress(toAddress)), - Value: NewUnit(amount, EtherUnitEther).Value(EtherUnitWei).BigInt(), - }) - if err != nil { - return nil, fmt.Errorf("failed to estimate gas for eth: %w", err) - } - - gasAmount = decimal.NewFromUint64(estimatedGas) - gasTipCap = estimate.SuggestGasTipCap - totalGasPrice = estimate.MaxFeePerGas - totalFeeAmount = totalGasPrice.Mul(gasAmount) + gasAmount, err = s.estimateNativeAssetGas(ctx, fromAddress, toAddress, amount) } else { - amount = amount.Mul(decimal.NewFromInt(1).Mul(decimal.NewFromInt(10).Pow(decimal.NewFromInt(decimals)))) - - data, err := s.abi.Pack("transfer", common.HexToAddress(toAddress), amount.BigInt()) - if err != nil { - return nil, fmt.Errorf("failed to pack transfer data: %w", err) - } - - estimatedGas, err := s.node.EstimateGas(ctx, ethereum.CallMsg{ - From: common.HexToAddress(fromAddress), - To: utils.Pointer(common.HexToAddress(assetIdentifier)), - Data: data, - }) - if err != nil { - return nil, fmt.Errorf("failed to estimate gas for contract: %w", err) - } - - gasAmount = decimal.NewFromUint64(estimatedGas) - gasTipCap = estimate.SuggestGasTipCap - totalGasPrice = estimate.MaxFeePerGas - totalFeeAmount = totalGasPrice.Mul(gasAmount) + gasAmount, err = s.estimateTokenGas(ctx, fromAddress, toAddress, assetIdentifier, amount, decimals) + } + if err != nil { + return nil, err } + gasTipCap := estimate.SuggestGasTipCap + totalGasPrice := estimate.MaxFeePerGas + totalFeeAmount := totalGasPrice.Mul(gasAmount) + return &EstimateTransferResult{ TotalFeeAmount: totalFeeAmount, TotalGasPrice: totalGasPrice, @@ -78,6 +50,48 @@ func (s *EVM) EstimateTransfer(ctx context.Context, fromAddress, toAddress, asse }, nil } +// estimateNativeAssetGas estimates gas for native blockchain asset transfers +func (s *EVM) estimateNativeAssetGas(ctx context.Context, fromAddress, toAddress string, amount decimal.Decimal) (decimal.Decimal, error) { + estimatedGas, err := s.node.EstimateGas(ctx, ethereum.CallMsg{ + From: common.HexToAddress(fromAddress), + To: utils.Pointer(common.HexToAddress(toAddress)), + Value: NewUnit(amount, EtherUnitEther).Value(EtherUnitWei).BigInt(), + }) + if err != nil { + return decimal.Zero, fmt.Errorf("failed to estimate gas for eth: %w", err) + } + + // Use the actual gas limit that will be used in transaction + gasLimit := GasLimitByBlockchain(s.config.Blockchain) + + if estimatedGas > gasLimit { + return decimal.NewFromUint64(estimatedGas), nil + } + return decimal.NewFromUint64(gasLimit), nil +} + +// estimateTokenGas estimates gas for token (ERC-20) transfers +func (s *EVM) estimateTokenGas(ctx context.Context, fromAddress, toAddress, assetIdentifier string, amount decimal.Decimal, decimals int64) (decimal.Decimal, error) { + // Convert amount to token's smallest unit + amount = amount.Mul(decimal.NewFromInt(1).Mul(decimal.NewFromInt(10).Pow(decimal.NewFromInt(decimals)))) + + data, err := s.abi.Pack("transfer", common.HexToAddress(toAddress), amount.BigInt()) + if err != nil { + return decimal.Zero, fmt.Errorf("failed to pack transfer data: %w", err) + } + + estimatedGas, err := s.node.EstimateGas(ctx, ethereum.CallMsg{ + From: common.HexToAddress(fromAddress), + To: utils.Pointer(common.HexToAddress(assetIdentifier)), + Data: data, + }) + if err != nil { + return decimal.Zero, fmt.Errorf("failed to estimate gas for contract: %w", err) + } + + return decimal.NewFromUint64(estimatedGas), nil +} + // EstimateFeeResult represents the result of the fee estimation // // All values are in Wei @@ -133,7 +147,11 @@ func (s *EVM) EstimateFee(ctx context.Context) (*EstimateFeeResult, error) { fee.SuggestGasTipCap = minGasTipCap } - fee.MaxFeePerGas = GetBaseFeeMultiplier(fee.SuggestGasPrice).Add(fee.SuggestGasTipCap) + fee.MaxFeePerGas = GetBaseFeeMultiplier(fee.SuggestGasPrice) + + if fee.MaxFeePerGas.LessThan(fee.SuggestGasPrice.Add(fee.SuggestGasTipCap)) { + fee.MaxFeePerGas = fee.SuggestGasPrice.Add(fee.SuggestGasTipCap) + } return fee, nil } @@ -157,6 +175,16 @@ func getMinGasTipCapByBlockchain(blockchain wconstants.BlockchainType) decimal.D } } +// GasLimitByBlockchain returns the gas limit by blockchain for base asset transfers. +func GasLimitByBlockchain(blockchain wconstants.BlockchainType) uint64 { + switch blockchain { + case wconstants.BlockchainTypeArbitrum: + return 38000 + default: + return 21000 // Default gas limit for unknown blockchains + } +} + func GetBaseFeeMultiplier(baseFeeWei decimal.Decimal) decimal.Decimal { items := []struct { threshold int64 diff --git a/pkg/walletsdk/evm/wallet.go b/pkg/walletsdk/evm/wallet.go index cd6046e..3773cb8 100644 --- a/pkg/walletsdk/evm/wallet.go +++ b/pkg/walletsdk/evm/wallet.go @@ -1,14 +1,14 @@ package evm import ( + "crypto/ecdsa" "encoding/hex" "errors" "strconv" "strings" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/dv-net/go-bip39" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/fbsobreira/gotron-sdk/pkg/keys/hd" ) @@ -20,12 +20,12 @@ func NewWalletSDK() *WalletSDK { return &WalletSDK{} } -func WalletPubKeyHash(mnemonic string, passphrase string, sequence uint32) (string, *btcec.PrivateKey, *btcec.PublicKey, error) { +func WalletPubKeyHash(mnemonic string, passphrase string, sequence uint32) (string, *ecdsa.PrivateKey, *ecdsa.PublicKey, error) { seed := bip39.NewSeed(mnemonic, passphrase) secret, chainCode := hd.ComputeMastersFromSeed(seed, []byte("Bitcoin seed")) secret, err := hd.DerivePrivateKeyForPath( - btcec.S256(), + crypto.S256(), secret, chainCode, "44'/60'/0'/0/"+strconv.Itoa(int(sequence)), @@ -34,10 +34,13 @@ func WalletPubKeyHash(mnemonic string, passphrase string, sequence uint32) (stri return "", nil, nil, errors.New("failed to derive private key") } - privateKey, publicKey := secp256k1.PrivKeyFromBytes(secret[:]), secp256k1.PrivKeyFromBytes(secret[:]).PubKey() - address := crypto.PubkeyToAddress(*publicKey.ToECDSA()) + privateKey, err := crypto.ToECDSA(secret[:]) + if err != nil { + return "", nil, nil, errors.New("failed to generate ECDSA from secret") + } + address := crypto.PubkeyToAddress(privateKey.PublicKey) - return strings.ToLower(address.String()), privateKey, publicKey, nil + return strings.ToLower(address.String()), privateKey, &privateKey.PublicKey, nil } func AddressWallet(mnemonic string, passphrase string, sequence uint32) (string, error) { @@ -57,7 +60,7 @@ func AddressSecret(address string, mnemonic string, passphrase string, sequence if !strings.EqualFold(address, wAddress) { return "", errors.New("generate private key address") } - return private.Key.String(), nil + return hexutil.Encode(crypto.FromECDSA(private)), nil } func AddressPublic(address string, mnemonic string, passphrase string, sequence uint32) (string, error) { @@ -68,7 +71,7 @@ func AddressPublic(address string, mnemonic string, passphrase string, sequence if !strings.EqualFold(address, wAddress) { return "", errors.New("generate private key address") } - return hex.EncodeToString(public.SerializeUncompressed()), nil + return hex.EncodeToString(crypto.FromECDSAPub(public)), nil } func (s WalletSDK) ValidateAddress(address string) bool { diff --git a/pkg/walletsdk/evm/wallet_test.go b/pkg/walletsdk/evm/wallet_test.go index f0ec3c0..b84e531 100644 --- a/pkg/walletsdk/evm/wallet_test.go +++ b/pkg/walletsdk/evm/wallet_test.go @@ -5,10 +5,9 @@ import ( "strconv" "testing" - "github.com/btcsuite/btcd/btcec/v2" - secp "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/dv-net/dv-processing/pkg/walletsdk/evm" "github.com/dv-net/go-bip39" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/fbsobreira/gotron-sdk/pkg/keys/hd" "github.com/stretchr/testify/require" @@ -16,8 +15,8 @@ import ( const ( mnemonic = "vague wool express sniff alley core hen symptom end rather month cave cross elder nest bright paddle use voice wife dolphin mosquito inside curve" - passphrase = "asdfasdfasdf" //nolint:gosec - defaultSequence = 1 + passphrase = "" //nolint:gosec + defaultSequence = 0 ) func Test_GenerateAddresses(t *testing.T) { @@ -27,18 +26,18 @@ func Test_GenerateAddresses(t *testing.T) { t.Fatalf("failed to generate addresss: %v", err) } - fmt.Println(addr, priv) + fmt.Println(addr, hexutil.Encode(crypto.FromECDSA(priv))) } } func TestEthereumWalletPubKeyHash(t *testing.T) { seed := bip39.NewSeed(mnemonic, passphrase) require.NotEmpty(t, seed) - secret, chainCode := hd.ComputeMastersFromSeed(seed, []byte(passphrase)) + secret, chainCode := hd.ComputeMastersFromSeed(seed, []byte("Bitcoin seed")) require.NotEmpty(t, secret) require.NotEmpty(t, chainCode) secret, err := hd.DerivePrivateKeyForPath( - btcec.S256(), + crypto.S256(), secret, chainCode, "44'/60'/0'/0/"+strconv.Itoa(defaultSequence), @@ -46,14 +45,14 @@ func TestEthereumWalletPubKeyHash(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, secret) - privateKey, publicKey := secp.PrivKeyFromBytes(secret[:]), secp.PrivKeyFromBytes(secret[:]).PubKey() + privateKey, err := crypto.ToECDSA(secret[:]) + require.NoError(t, err) require.NotEmpty(t, privateKey) - require.NotEmpty(t, publicKey) - address := crypto.PubkeyToAddress(*publicKey.ToECDSA()) + address := crypto.PubkeyToAddress(privateKey.PublicKey) require.NotEmpty(t, address) - t.Log(address.String()) - t.Log(publicKey.ToECDSA()) - t.Log(privateKey.Key.String()) + t.Log(address.String()) + t.Log(hexutil.Encode(crypto.FromECDSA(privateKey))) + t.Log(hexutil.Encode(crypto.FromECDSAPub(&privateKey.PublicKey))) } diff --git a/pkg/walletsdk/tron/reclaim.go b/pkg/walletsdk/tron/reclaim.go index b8ee455..9ea0729 100644 --- a/pkg/walletsdk/tron/reclaim.go +++ b/pkg/walletsdk/tron/reclaim.go @@ -79,7 +79,7 @@ func (t *Tron) ReclaimResource(ctx context.Context, params ReclaimResourceParams return nil, fmt.Errorf("create reclaim tx error: %s", string(tx.Result.Message)) } - if err := t.SignTransaction(tx.GetTransaction(), priv.ToECDSA()); err != nil { + if err := t.SignTransaction(tx.GetTransaction(), priv); err != nil { return nil, fmt.Errorf("sign transaction: %w", err) } diff --git a/pkg/walletsdk/tron/resources.go b/pkg/walletsdk/tron/resources.go index 8c7b36b..02335ac 100644 --- a/pkg/walletsdk/tron/resources.go +++ b/pkg/walletsdk/tron/resources.go @@ -8,7 +8,6 @@ import ( "strings" "time" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/dv-net/dv-processing/pkg/retry" "github.com/dv-net/dv-processing/rpccode" "github.com/ethereum/go-ethereum/crypto" @@ -883,12 +882,12 @@ func (t *Tron) fillFakeTX(tx *core.Transaction) error { return err } - pk, err := secp256k1.GeneratePrivateKey() + pk, err := crypto.GenerateKey() if err != nil { return err } - signature, err := crypto.Sign(h256h.Sum(nil), pk.ToECDSA()) + signature, err := crypto.Sign(h256h.Sum(nil), pk) if err != nil { return err } diff --git a/pkg/walletsdk/tron/resources_test.go b/pkg/walletsdk/tron/resources_test.go index bad5276..2c38d72 100644 --- a/pkg/walletsdk/tron/resources_test.go +++ b/pkg/walletsdk/tron/resources_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/fbsobreira/gotron-sdk/pkg/address" @@ -295,10 +294,10 @@ func TestEstimateEnergyForTransfer(t *testing.T) { _, err = h256h.Write(rawData) require.NoError(t, err) - pk, err := secp256k1.GeneratePrivateKey() + pk, err := crypto.GenerateKey() require.NoError(t, err) - signature, err := crypto.Sign(h256h.Sum(nil), pk.ToECDSA()) + signature, err := crypto.Sign(h256h.Sum(nil), pk) require.NoError(t, err) tx.Signature = append(tx.Signature, signature) diff --git a/pkg/walletsdk/tron/tron_test.go b/pkg/walletsdk/tron/tron_test.go index 1b33669..120d10b 100644 --- a/pkg/walletsdk/tron/tron_test.go +++ b/pkg/walletsdk/tron/tron_test.go @@ -6,12 +6,11 @@ import ( "strconv" "testing" - "github.com/btcsuite/btcd/btcec/v2" - secp "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/dv-net/dv-processing/pkg/testutils" "github.com/dv-net/dv-processing/pkg/walletsdk/tron" "github.com/dv-net/go-bip39" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" addr "github.com/fbsobreira/gotron-sdk/pkg/address" "github.com/fbsobreira/gotron-sdk/pkg/keys/hd" "github.com/fbsobreira/gotron-sdk/pkg/proto/api" @@ -21,7 +20,7 @@ import ( const ( mnemonic = "vague wool express sniff alley core hen symptom end rather month cave cross elder nest bright paddle use voice wife dolphin mosquito inside curve" passphrase = "" //nolint:gosec - defaultSequence = 1 + defaultSequence = 0 ) func Test_GenerateAddresses(t *testing.T) { @@ -41,11 +40,11 @@ func TestTronWalletPubKeyHash(t *testing.T) { t.Run("", func(t *testing.T) { seed := bip39.NewSeed(mnemonic, passphrase) require.NotEmpty(t, seed) - secret, chainCode := hd.ComputeMastersFromSeed(seed, []byte(passphrase)) + secret, chainCode := hd.ComputeMastersFromSeed(seed, []byte("Bitcoin seed")) require.NotEmpty(t, secret) require.NotEmpty(t, chainCode) secret, err := hd.DerivePrivateKeyForPath( - btcec.S256(), + crypto.S256(), secret, chainCode, "44'/195'/0'/0/"+strconv.Itoa(defaultSequence), @@ -53,16 +52,27 @@ func TestTronWalletPubKeyHash(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, secret) - privateKey, publicKey := secp.PrivKeyFromBytes(secret[:]), secp.PrivKeyFromBytes(secret[:]).PubKey() + privateKey, err := crypto.ToECDSA(secret[:]) require.NotEmpty(t, privateKey) - require.NotEmpty(t, publicKey) + require.NoError(t, err) + + publicKey := privateKey.PublicKey - address := addr.PubkeyToAddress(*publicKey.ToECDSA()).String() + address := addr.PubkeyToAddress(publicKey).String() require.NotEmpty(t, address) - t.Log(address) - t.Log(hexutil.Encode(publicKey.SerializeCompressed())) - t.Log(hexutil.Encode(privateKey.Serialize())) + { + walletAddress := address + require.Equal(t, walletAddress, "TNhpnt7RTBbqHJ6KXARXNXzP3DmCLeda9t") + walletPublicKey := hexutil.Encode(crypto.CompressPubkey(&publicKey)) + require.Equal(t, walletPublicKey, "0x022f7180d4139d93e139bb54eaea8950a6d63e73c1ccbdc5a67648ca46c24d7890") + walletPrivateKey := hexutil.Encode(crypto.FromECDSA(privateKey)) + require.Equal(t, walletPrivateKey, "0xed809dfbae236bef30e235f4c871736205b58cf387167ded93ebcbc20865b0ef") + + } + t.Log(address) + t.Log(hexutil.Encode(crypto.CompressPubkey(&publicKey))) + t.Log(hexutil.Encode(crypto.FromECDSA(privateKey))) }) } @@ -70,7 +80,7 @@ func TestTronWalletPubKeyHash(t *testing.T) { func TestAddressSecret(t *testing.T) { _, private, _, err := tron.WalletPubKeyHash(mnemonic, passphrase, defaultSequence) require.NoError(t, err) - t.Log(private) + t.Log(hexutil.Encode(crypto.FromECDSA(private))) } func TestGetAllChainParams(t *testing.T) { @@ -100,7 +110,7 @@ func TestIsAccountActivated(t *testing.T) { }{ { // currently this address is not activated - address: "TRDGZSLHBdp4a2RCfY7basfKzGdxJug184", + address: "TD76i6fcmbZrfWqRVgmM6aEKZCVevy4Fmv", isActivated: false, }, { diff --git a/pkg/walletsdk/tron/wallet.go b/pkg/walletsdk/tron/wallet.go index c67f183..026df74 100644 --- a/pkg/walletsdk/tron/wallet.go +++ b/pkg/walletsdk/tron/wallet.go @@ -1,12 +1,14 @@ package tron import ( - "encoding/hex" + "crypto/ecdsa" + "errors" "fmt" "strconv" - "github.com/btcsuite/btcd/btcec/v2" "github.com/dv-net/go-bip39" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" addr "github.com/fbsobreira/gotron-sdk/pkg/address" "github.com/fbsobreira/gotron-sdk/pkg/keys/hd" ) @@ -18,12 +20,12 @@ func NewWalletSDK() *WalletSDK { return &WalletSDK{} } -func WalletPubKeyHash(mnemonic string, passphrase string, sequence uint32) (string, *btcec.PrivateKey, *btcec.PublicKey, error) { +func WalletPubKeyHash(mnemonic string, passphrase string, sequence uint32) (string, *ecdsa.PrivateKey, *ecdsa.PublicKey, error) { seed := bip39.NewSeed(mnemonic, passphrase) secret, chainCode := hd.ComputeMastersFromSeed(seed, []byte("Bitcoin seed")) secret, err := hd.DerivePrivateKeyForPath( - btcec.S256(), + crypto.S256(), secret, chainCode, "44'/195'/0'/0/"+strconv.Itoa(int(sequence)), @@ -32,11 +34,14 @@ func WalletPubKeyHash(mnemonic string, passphrase string, sequence uint32) (stri return "", nil, nil, fmt.Errorf("failed to derive private key: %w", err) } - privateKey, publicKey := btcec.PrivKeyFromBytes(secret[:]) + privateKey, err := crypto.ToECDSA(secret[:]) + if err != nil { + return "", nil, nil, errors.New("failed to generate ECDSA from secret") + } - address := addr.PubkeyToAddress(*publicKey.ToECDSA()).String() + address := addr.PubkeyToAddress(privateKey.PublicKey) - return address, privateKey, publicKey, nil + return address.String(), privateKey, &privateKey.PublicKey, nil } func AddressWallet(mnemonic string, passphrase string, sequence uint32) (string, error) { @@ -56,7 +61,7 @@ func AddressSecret(address string, mnemonic string, passphrase string, sequence if address != wAddress { return "", fmt.Errorf("generate private key address") } - return private.Key.String(), nil + return hexutil.Encode(crypto.FromECDSA(private)), nil } func AddressPublic(address string, mnemonic string, passphrase string, sequence uint32) (string, error) { @@ -67,12 +72,16 @@ func AddressPublic(address string, mnemonic string, passphrase string, sequence if address != wAddress { return "", fmt.Errorf("generate private key address") } - return hex.EncodeToString(public.SerializeCompressed()), nil + return hexutil.Encode(crypto.FromECDSAPub(public)), nil } -func WalletFromPrivateKeyBytes(privateKey []byte) (string, *btcec.PrivateKey, *btcec.PublicKey) { - priv, pub := btcec.PrivKeyFromBytes(privateKey) - return addr.PubkeyToAddress(*pub.ToECDSA()).String(), priv, pub +func WalletFromPrivateKeyBytes(privateKey []byte) (string, *ecdsa.PrivateKey, *ecdsa.PublicKey) { + private, err := crypto.ToECDSA(privateKey) + if err != nil { + return "", nil, nil + } + address := addr.PubkeyToAddress(private.PublicKey) + return address.String(), private, &private.PublicKey } func (s WalletSDK) ValidateAddress(address string) bool {