| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- package service
- import (
- "context"
- "crypto/ecdsa"
- "crypto/sha256"
- "encoding/hex"
- "errors"
- "fmt"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- tronaddr "github.com/fbsobreira/gotron-sdk/pkg/address"
- troncore "github.com/fbsobreira/gotron-sdk/pkg/proto/core"
- "google.golang.org/protobuf/proto"
- "key-manager/dao"
- "math/big"
- )
- func format(network, address string) (string, error) {
- if network == eth {
- address = common.HexToAddress(address).String()
- } else {
- addr, err := tronaddr.Base58ToAddress(address)
- if err != nil {
- return "", err
- }
- address = addr.String()
- }
- return address, nil
- }
- func (km *KeyManager) loadSigner(network, signer string) error {
- var err error
- signer, err = format(network, signer)
- if err != nil {
- return err
- }
- if _, ok := km.signers[signer]; !ok {
- var info dao.AccountInfo
- if network == eth {
- info, err = km.dao.GetEthFromAddress(signer)
- if err != nil {
- return err
- }
- } else {
- info, err = km.dao.GetTronFromAddress(signer)
- if err != nil {
- return err
- }
- }
- if _, exist := km.mnemonics[info.GetName()]; !exist {
- return errors.New("user mnemonic lost")
- }
- account, err := createKey(km.mnemonics[info.GetName()], network, info.GetIndex())
- if err != nil {
- return err
- }
- km.signers[signer] = account.GetPriKey()
- }
- return nil
- }
- func (km *KeyManager) Sign(ctx context.Context, req *SignRequest) (*SignResponse, error) {
- km.lk.Lock()
- defer km.lk.Unlock()
- if err := checkNetwork(req.Network); err != nil {
- return &SignResponse{
- Code: networkErrCode,
- Msg: networkErrMsg,
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- if err := km.loadSigner(req.Network, req.Sender); err != nil {
- return &SignResponse{
- Code: loadSignerErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- var marshalTx string
- var coin string
- var to string
- var amount string
- if req.Network == eth {
- tx, err := unmarshalJEthTx(req.Tx)
- if err != nil {
- return &SignResponse{
- Code: unmarshalJEthTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- coin, to, amount, err = checkErc(tx, km.whitelists)
- if err != nil {
- return &SignResponse{
- Code: checkErcTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- signedTx, err := signEthTransaction(tx, km.signers[req.Sender])
- if err != nil {
- return &SignResponse{
- Code: signEthTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- marshalTx, err = marshalJEthTx(signedTx)
- if err != nil {
- return &SignResponse{
- Code: marshalJEthTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- } else {
- tx, err := unmarshalJTronTx(req.Tx)
- if err != nil {
- return &SignResponse{
- Code: unmarshalJTronTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- coin, to, amount, err = checkTron(tx, km.whitelists)
- if err != nil {
- return &SignResponse{
- Code: checkTronTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- signedTx, err := signTronTransaction(tx, km.signers[req.Sender])
- if err != nil {
- return &SignResponse{
- Code: signTronTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- marshalTx, err = marshalJTronTx(signedTx)
- if err != nil {
- return &SignResponse{
- Code: marshalJTronTxErrCode,
- Msg: err.Error(),
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: "",
- }, nil
- }
- }
- err := km.dao.CreateSignTx(&dao.SignTx{
- Network: req.Network,
- Coin: coin,
- From: req.Sender,
- To: to,
- Amount: amount,
- })
- if err != nil {
- log.Warnw("save Sign Tx to mysql failed", "network", req.Network, "coin", coin, "from", req.Sender, "to", to, "amount", amount, "err", err)
- }
- return &SignResponse{
- Code: okCode,
- Msg: okMsg,
- Network: req.Network,
- Sender: req.Sender,
- SignedTx: marshalTx,
- }, nil
- }
- func marshalJEthTx(transaction *types.Transaction) (string, error) {
- b, err := transaction.MarshalJSON()
- if err != nil {
- return "", err
- }
- return hex.EncodeToString(b), nil
- }
- func unmarshalJEthTx(tx string) (*types.Transaction, error) {
- b, err := hex.DecodeString(tx)
- if err != nil {
- return nil, err
- }
- var transaction = &types.Transaction{}
- err = transaction.UnmarshalJSON(b)
- if err != nil {
- return nil, err
- }
- return transaction, err
- }
- func marshalJTronTx(transaction *troncore.Transaction) (string, error) {
- b, err := proto.Marshal(transaction)
- if err != nil {
- return "", err
- }
- return hex.EncodeToString(b), nil
- }
- func unmarshalJTronTx(tx string) (*troncore.Transaction, error) {
- b, err := hex.DecodeString(tx)
- if err != nil {
- return nil, err
- }
- var transaction troncore.Transaction
- err = proto.Unmarshal(b, &transaction)
- if err != nil {
- return nil, err
- }
- return &transaction, nil
- }
- func signEthTransaction(transaction *types.Transaction, priv *ecdsa.PrivateKey) (*types.Transaction, error) {
- signer := types.NewLondonSigner(big.NewInt(1))
- var err error
- transaction, err = types.SignTx(transaction, signer, priv)
- if err != nil {
- return nil, err
- }
- return transaction, nil
- }
- func signTronTransaction(transaction *troncore.Transaction, priv *ecdsa.PrivateKey) (*troncore.Transaction, error) {
- rawData, err := proto.Marshal(transaction.GetRawData())
- if err != nil {
- return nil, fmt.Errorf("proto marshal tx raw data error: %v", err)
- }
- h256h := sha256.New()
- h256h.Write(rawData)
- hash := h256h.Sum(nil)
- signature, err := crypto.Sign(hash, priv)
- if err != nil {
- return nil, fmt.Errorf("sign error: %v", err)
- }
- transaction.Signature = append(transaction.Signature, signature)
- return transaction, nil
- }
|