github.com/annchain/OG@v0.0.9/rpc/tx_controller.go (about)

     1  // Copyright © 2019 Annchain Authors <EMAIL ADDRESS>
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package rpc
    15  
    16  //go:generate msgp
    17  import (
    18  	"fmt"
    19  	types2 "github.com/annchain/OG/arefactor/og/types"
    20  	"github.com/annchain/OG/arefactor/og_interface"
    21  	"github.com/annchain/OG/og/types"
    22  	"github.com/annchain/OG/og/types/archive"
    23  
    24  	"net/http"
    25  	"strconv"
    26  	"time"
    27  
    28  	"github.com/annchain/OG/common"
    29  	"github.com/annchain/OG/common/crypto"
    30  	"github.com/annchain/OG/common/math"
    31  	"github.com/annchain/OG/status"
    32  	"github.com/gin-gonic/gin"
    33  	"github.com/sirupsen/logrus"
    34  )
    35  
    36  func (r *RpcController) NewTransaction(c *gin.Context) {
    37  	var (
    38  		tx    types.Txi
    39  		txReq NewTxRequest
    40  		sig   crypto.Signature
    41  		pub   crypto.PublicKey
    42  	)
    43  
    44  	if status.ArchiveMode {
    45  		Response(c, http.StatusBadRequest, fmt.Errorf("archive mode"), nil)
    46  		return
    47  	}
    48  
    49  	err := c.ShouldBindJSON(&txReq)
    50  	if err != nil {
    51  		Response(c, http.StatusBadRequest, fmt.Errorf("request format error: %v", err), nil)
    52  		return
    53  	}
    54  	from, err := common.StringToAddress(txReq.From)
    55  	if err != nil {
    56  		Response(c, http.StatusBadRequest, fmt.Errorf("from address format error: %v", err), nil)
    57  		return
    58  	}
    59  	to, err := common.StringToAddress(txReq.To)
    60  	if err != nil {
    61  		Response(c, http.StatusBadRequest, fmt.Errorf("to address format error: %v", err), nil)
    62  		return
    63  	}
    64  
    65  	value, ok := math.NewBigIntFromString(txReq.Value, 10)
    66  	if !ok {
    67  		err = fmt.Errorf("new Big Int error")
    68  	}
    69  	if err != nil {
    70  		Response(c, http.StatusBadRequest, fmt.Errorf("value format error: %v", err), nil)
    71  		return
    72  	}
    73  
    74  	data := common.FromHex(txReq.Data)
    75  	if data == nil {
    76  		Response(c, http.StatusBadRequest, fmt.Errorf("data not hex"), nil)
    77  		return
    78  	}
    79  
    80  	nonce, err := strconv.ParseUint(txReq.Nonce, 10, 64)
    81  	if err != nil {
    82  		Response(c, http.StatusBadRequest, fmt.Errorf("nonce format error"), nil)
    83  		return
    84  	}
    85  
    86  	signature := common.FromHex(txReq.Signature)
    87  	if signature == nil || txReq.Signature == "" {
    88  		Response(c, http.StatusBadRequest, fmt.Errorf("signature format error"), nil)
    89  		return
    90  	}
    91  
    92  	if txReq.CryptoType == "" {
    93  		pub, err = crypto.PublicKeyFromString(txReq.Pubkey)
    94  		if err != nil {
    95  			Response(c, http.StatusBadRequest, fmt.Errorf("pubkey format error %v", err), nil)
    96  			return
    97  		}
    98  	} else {
    99  
   100  		pub, err = crypto.PublicKeyFromStringWithCryptoType(txReq.CryptoType, txReq.Pubkey)
   101  		if err != nil {
   102  			Response(c, http.StatusBadRequest, fmt.Errorf("pubkey format error %v", err), nil)
   103  			return
   104  		}
   105  	}
   106  
   107  	sig = crypto.SignatureFromBytes(pub.Type, signature)
   108  	if sig.Type != og_interface.Signer.GetCryptoType() || pub.Type != og_interface.Signer.GetCryptoType() {
   109  		Response(c, http.StatusOK, fmt.Errorf("ogcrypto algorithm mismatch"), nil)
   110  		return
   111  	}
   112  
   113  	tx, err = r.TxCreator.NewTxWithSeal(ogcore.TxWithSealBuildRequest{
   114  		From:    from,
   115  		To:      to,
   116  		Value:   value,
   117  		Data:    data,
   118  		Nonce:   nonce,
   119  		Pubkey:  pub,
   120  		Sig:     sig,
   121  		TokenId: txReq.TokenId,
   122  	})
   123  	if err != nil {
   124  		Response(c, http.StatusInternalServerError, fmt.Errorf("new tx failed %v", err), nil)
   125  		return
   126  	}
   127  
   128  	ok = r.FormatVerifier.VerifySignature(tx)
   129  	if !ok {
   130  		logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("signature invalid")
   131  		Response(c, http.StatusInternalServerError, fmt.Errorf("signature invalid"), nil)
   132  		return
   133  	}
   134  	ok = r.FormatVerifier.VerifySourceAddress(tx)
   135  	if !ok {
   136  		logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("source address invalid")
   137  		Response(c, http.StatusInternalServerError, fmt.Errorf("ource address invalid"), nil)
   138  		return
   139  	}
   140  	tx.SetVerified(archive.VerifiedFormat)
   141  	logrus.WithField("tx", tx).Debugf("tx generated")
   142  	if !r.SyncerManager.IncrementalSyncer.Enabled {
   143  		Response(c, http.StatusOK, fmt.Errorf("tx is disabled when syncing"), nil)
   144  		return
   145  	}
   146  
   147  	r.TxBuffer.ReceivedNewTxChan <- tx
   148  
   149  	Response(c, http.StatusOK, nil, tx.GetHash().Hex())
   150  	return
   151  }
   152  
   153  //NewTxrequest for RPC request
   154  //msgp:tuple NewTxRequest
   155  type NewTxRequest struct {
   156  	Nonce      string `json:"nonce"`
   157  	From       string `json:"from"`
   158  	To         string `json:"to"`
   159  	Value      string `json:"value"`
   160  	Data       string `json:"data"`
   161  	CryptoType string `json:"crypto_type"`
   162  	Signature  string `json:"signature"`
   163  	Pubkey     string `json:"pubkey"`
   164  	TokenId    int32  `json:"token_id"`
   165  }
   166  
   167  //msgp:tuple NewTxsRequests
   168  type NewTxsRequests struct {
   169  	Txs []NewTxRequest `json:"txs"`
   170  }
   171  
   172  func (r *RpcController) NewTransactions(c *gin.Context) {
   173  	var (
   174  		//txs types.Txis
   175  		txrequsets NewTxsRequests
   176  		sig        crypto.Signature
   177  		pub        crypto.PublicKey
   178  		hashes     types2.Hashes
   179  	)
   180  
   181  	if status.ArchiveMode {
   182  		Response(c, http.StatusBadRequest, fmt.Errorf("archive mode"), nil)
   183  		return
   184  	}
   185  
   186  	err := c.ShouldBindJSON(&txrequsets)
   187  	if err != nil || len(txrequsets.Txs) == 0 {
   188  		Response(c, http.StatusBadRequest, fmt.Errorf("request format error: %v", err), nil)
   189  		return
   190  	}
   191  	for i, txReq := range txrequsets.Txs {
   192  		var tx types.Txi
   193  		from, err := common.StringToAddress(txReq.From)
   194  		if err != nil {
   195  			Response(c, http.StatusBadRequest, fmt.Errorf("from address format error: %v", err), nil)
   196  			return
   197  		}
   198  		to, err := common.StringToAddress(txReq.To)
   199  		if err != nil {
   200  			Response(c, http.StatusBadRequest, fmt.Errorf("to address format error: %v", err), nil)
   201  			return
   202  		}
   203  
   204  		value, ok := math.NewBigIntFromString(txReq.Value, 10)
   205  		if !ok {
   206  			err = fmt.Errorf("new Big Int error")
   207  		}
   208  		if err != nil {
   209  			Response(c, http.StatusBadRequest, fmt.Errorf("value format error: %v", err), nil)
   210  			return
   211  		}
   212  
   213  		data := common.FromHex(txReq.Data)
   214  		if data == nil {
   215  			Response(c, http.StatusBadRequest, fmt.Errorf("data not hex"), nil)
   216  			return
   217  		}
   218  
   219  		nonce, err := strconv.ParseUint(txReq.Nonce, 10, 64)
   220  		if err != nil {
   221  			Response(c, http.StatusBadRequest, fmt.Errorf("nonce format error"), nil)
   222  			return
   223  		}
   224  
   225  		signature := common.FromHex(txReq.Signature)
   226  		if signature == nil {
   227  			Response(c, http.StatusBadRequest, fmt.Errorf("signature format error"), nil)
   228  			return
   229  		}
   230  
   231  		if txReq.CryptoType == "" {
   232  			pub, err = crypto.PublicKeyFromString(txReq.Pubkey)
   233  			if err != nil {
   234  				Response(c, http.StatusBadRequest, fmt.Errorf("pubkey format error %v", err), nil)
   235  				return
   236  			}
   237  		} else {
   238  
   239  			pub, err = crypto.PublicKeyFromStringWithCryptoType(txReq.CryptoType, txReq.Pubkey)
   240  			if err != nil {
   241  				Response(c, http.StatusBadRequest, fmt.Errorf("pubkey format error %v", err), nil)
   242  				return
   243  			}
   244  		}
   245  
   246  		sig = crypto.SignatureFromBytes(pub.Type, signature)
   247  		if sig.Type != og_interface.Signer.GetCryptoType() || pub.Type != og_interface.Signer.GetCryptoType() {
   248  			Response(c, http.StatusOK, fmt.Errorf("ogcrypto algorithm mismatch"), nil)
   249  			return
   250  		}
   251  		if !r.SyncerManager.IncrementalSyncer.Enabled {
   252  			Response(c, http.StatusOK, fmt.Errorf("tx is disabled when syncing"), nil)
   253  			return
   254  		}
   255  		tx, err = r.TxCreator.NewTxWithSeal(ogcore.TxWithSealBuildRequest{
   256  			From:    from,
   257  			To:      to,
   258  			Value:   value,
   259  			Data:    data,
   260  			Nonce:   nonce,
   261  			Pubkey:  pub,
   262  			Sig:     sig,
   263  			TokenId: txReq.TokenId,
   264  		})
   265  		if err != nil {
   266  			//try second time
   267  			logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("gen tx failed , try again")
   268  			ok = r.FormatVerifier.VerifySignature(tx)
   269  			if !ok {
   270  				logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("signature invalid")
   271  				Response(c, http.StatusInternalServerError, fmt.Errorf("signature invalid"), nil)
   272  				return
   273  			}
   274  			ok = r.FormatVerifier.VerifySourceAddress(tx)
   275  			if !ok {
   276  				logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("source address invalid")
   277  				Response(c, http.StatusInternalServerError, fmt.Errorf("ource address invalid"), nil)
   278  				return
   279  			}
   280  			time.Sleep(time.Microsecond * 2)
   281  			tx, err = r.TxCreator.NewTxWithSeal(ogcore.TxWithSealBuildRequest{
   282  				From:    from,
   283  				To:      to,
   284  				Value:   value,
   285  				Data:    data,
   286  				Nonce:   nonce,
   287  				Pubkey:  pub,
   288  				Sig:     sig,
   289  				TokenId: txReq.TokenId,
   290  			})
   291  			if err != nil {
   292  				logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("gen tx failed")
   293  				Response(c, http.StatusInternalServerError, fmt.Errorf("new tx failed %v", err), nil)
   294  				return
   295  			}
   296  			logrus.WithField("i ", i).WithField("tx", tx).Debugf("tx generated after retry")
   297  			//we don't verify hash , since we calculated the hash
   298  			tx.SetVerified(archive.VerifiedFormat)
   299  			r.TxBuffer.ReceivedNewTxChan <- tx
   300  			hashes = append(hashes, tx.GetHash())
   301  			continue
   302  		}
   303  		logrus.WithField("i ", i).WithField("tx", tx).Debugf("tx generated")
   304  		//txs = append(txs,tx)
   305  		ok = r.FormatVerifier.VerifySignature(tx)
   306  		if !ok {
   307  			logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("signature invalid")
   308  			Response(c, http.StatusInternalServerError, fmt.Errorf("signature invalid"), nil)
   309  			return
   310  		}
   311  		ok = r.FormatVerifier.VerifySourceAddress(tx)
   312  		if !ok {
   313  			logrus.WithField("request ", txReq).WithField("tx ", tx).Warn("source address invalid")
   314  			Response(c, http.StatusInternalServerError, fmt.Errorf("ource address invalid"), nil)
   315  			return
   316  		}
   317  		//we don't verify hash , since we calculated the hash
   318  		tx.SetVerified(archive.VerifiedFormat)
   319  		r.TxBuffer.ReceivedNewTxChan <- tx
   320  		hashes = append(hashes, tx.GetHash())
   321  	}
   322  
   323  	//r.TxBuffer.ReceivedNewTxsChan <- txs
   324  
   325  	Response(c, http.StatusOK, nil, hashes)
   326  	return
   327  }