github.com/annchain/OG@v0.0.9/rpc/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  import (
    17  	"encoding/hex"
    18  	"fmt"
    19  	types2 "github.com/annchain/OG/arefactor/og/types"
    20  	"github.com/annchain/OG/arefactor/og_interface"
    21  	"github.com/annchain/OG/common"
    22  	"github.com/annchain/OG/consensus/annsensus"
    23  	"github.com/annchain/OG/consensus/campaign"
    24  	ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto"
    25  	"github.com/annchain/OG/og/archive"
    26  	"github.com/annchain/OG/og/txmaker"
    27  	"github.com/annchain/OG/og/types"
    28  	archive2 "github.com/annchain/OG/og/types/archive"
    29  	"github.com/annchain/OG/og/verifier"
    30  	"github.com/annchain/OG/ogcore/pool"
    31  	"github.com/annchain/OG/types/token"
    32  	"net/http"
    33  	"strconv"
    34  	"strings"
    35  
    36  	"github.com/annchain/OG/arefactor/performance"
    37  	"github.com/annchain/OG/og"
    38  	"github.com/annchain/OG/og/syncer"
    39  	"github.com/annchain/OG/p2p"
    40  	"github.com/gin-gonic/gin"
    41  )
    42  
    43  type RpcController struct {
    44  	P2pServer          *p2p.Server
    45  	Og                 *og.Og
    46  	TxBuffer           *pool.TxBuffer
    47  	TxCreator          *txmaker.OGTxCreator
    48  	SyncerManager      *syncer.SyncManager
    49  	PerformanceMonitor *performance.PerformanceMonitor
    50  	NewRequestChan     chan archive2.TxBaseType
    51  	AnnSensus          *annsensus.AnnSensus
    52  	FormatVerifier     *verifier.TxFormatVerifier
    53  }
    54  
    55  //TxRequester
    56  type TxRequester interface {
    57  	GenerateRequest(from int, to int)
    58  }
    59  
    60  //SequenceRequester
    61  type SequenceRequester interface {
    62  	GenerateRequest()
    63  }
    64  
    65  //NewArchiveRequest for RPC request
    66  type NewArchiveRequest struct {
    67  	Data []byte `json:"data"`
    68  }
    69  
    70  //NewAccountRequest for RPC request
    71  type NewAccountRequest struct {
    72  	Algorithm string `json:"algorithm"`
    73  }
    74  
    75  func cors(c *gin.Context) {
    76  	c.Header("Access-Control-Allow-Origin", "*")
    77  }
    78  
    79  //Query query
    80  func (r *RpcController) Query(c *gin.Context) {
    81  	Response(c, http.StatusOK, nil, "not implemented yet")
    82  }
    83  
    84  //Transaction  get  transaction
    85  func (r *RpcController) Transaction(c *gin.Context) {
    86  	hashtr := c.Query("hash")
    87  	hash, err := types2.HexToHash(hashtr)
    88  	cors(c)
    89  	if err != nil {
    90  		Response(c, http.StatusBadRequest, fmt.Errorf("hash format error"), nil)
    91  		return
    92  	}
    93  	txi := r.Og.Dag.GetTx(hash)
    94  	if txi == nil {
    95  		txi = r.Og.TxPool.Get(hash)
    96  	}
    97  	if txi == nil {
    98  		Response(c, http.StatusBadRequest, fmt.Errorf("tx not found"), nil)
    99  		return
   100  	}
   101  	switch tx := txi.(type) {
   102  	case *archive2.Tx:
   103  		Response(c, http.StatusOK, nil, tx)
   104  		return
   105  	case *types.Sequencer:
   106  		Response(c, http.StatusOK, nil, tx)
   107  		return
   108  	case *archive.Archive:
   109  		Response(c, http.StatusOK, nil, tx)
   110  		return
   111  	case *campaign.Campaign:
   112  		Response(c, http.StatusOK, nil, tx)
   113  		return
   114  	case *campaign.TermChange:
   115  		Response(c, http.StatusOK, nil, tx)
   116  		return
   117  	case *archive2.ActionTx:
   118  		Response(c, http.StatusOK, nil, tx)
   119  		return
   120  	}
   121  
   122  	Response(c, http.StatusNotFound, fmt.Errorf("status not found"), nil)
   123  }
   124  
   125  //Confirm checks if tx has already been confirmed.
   126  func (r *RpcController) Confirm(c *gin.Context) {
   127  	hashtr := c.Query("hash")
   128  	hash, err := types2.HexToHash(hashtr)
   129  	cors(c)
   130  	if err != nil {
   131  		Response(c, http.StatusBadRequest, fmt.Errorf("hash format error"), nil)
   132  		return
   133  	}
   134  	txiDag := r.Og.Dag.GetTx(hash)
   135  	txiTxpool := r.Og.TxPool.Get(hash)
   136  
   137  	if txiDag == nil && txiTxpool == nil {
   138  		Response(c, http.StatusNotFound, fmt.Errorf("tx not found"), nil)
   139  		return
   140  	}
   141  	if txiTxpool != nil {
   142  		Response(c, http.StatusOK, nil, false)
   143  		return
   144  		// c.JSON(http.StatusNotFound, gin.H{
   145  		// 	"confirm": false,
   146  		// })
   147  	} else {
   148  		Response(c, http.StatusOK, nil, true)
   149  		return
   150  		// c.JSON(http.StatusNotFound, gin.H{
   151  		// 	"confirm": true,
   152  		// })
   153  	}
   154  
   155  }
   156  
   157  //Transactions query Transactions
   158  func (r *RpcController) Transactions(c *gin.Context) {
   159  	seqId := c.Query("seq_id")
   160  	address := c.Query("address")
   161  	cors(c)
   162  	if address == "" {
   163  		id, err := strconv.Atoi(seqId)
   164  		if err != nil || id < 0 {
   165  			Response(c, http.StatusOK, fmt.Errorf("seq_id format error"), nil)
   166  			return
   167  		}
   168  		if r.Og.Dag.GetHeight() < uint64(id) {
   169  			Response(c, http.StatusOK, fmt.Errorf("txs not found"), nil)
   170  			return
   171  		}
   172  		txs := r.Og.Dag.GetTxisByNumber(uint64(id))
   173  		var txsResponse struct {
   174  			Total int        `json:"total"`
   175  			Txs   types.Txis `json:"txs"`
   176  		}
   177  		txsResponse.Total = len(txs)
   178  		txsResponse.Txs = txs
   179  		Response(c, http.StatusOK, nil, txsResponse)
   180  		return
   181  	} else {
   182  		addr, err := common.StringToAddress(address)
   183  		if err != nil {
   184  			Response(c, http.StatusOK, fmt.Errorf("address format error"), nil)
   185  			return
   186  		}
   187  		txs := r.Og.Dag.GetTxsByAddress(addr)
   188  		var txsResponse struct {
   189  			Total int         `json:"total"`
   190  			Txs   []types.Txi `json:"txs"`
   191  		}
   192  		if len(txs) != 0 {
   193  			txsResponse.Total = len(txs)
   194  			txsResponse.Txs = txs
   195  			Response(c, http.StatusOK, nil, txsResponse)
   196  			return
   197  		}
   198  		Response(c, http.StatusOK, fmt.Errorf("txs not found"), nil)
   199  		return
   200  	}
   201  
   202  }
   203  
   204  func (r *RpcController) Genesis(c *gin.Context) {
   205  	cors(c)
   206  	sq := r.Og.Dag.Genesis()
   207  	if sq != nil {
   208  		Response(c, http.StatusOK, nil, sq)
   209  	} else {
   210  		Response(c, http.StatusNotFound, fmt.Errorf("genesis not found"), nil)
   211  	}
   212  	return
   213  }
   214  
   215  func (r *RpcController) Sequencer(c *gin.Context) {
   216  	cors(c)
   217  	var sq *types.Sequencer
   218  	hashtr := c.Query("hash")
   219  	seqId := c.Query("seq_id")
   220  	if seqId == "" {
   221  		seqId = c.Query("id")
   222  	}
   223  	if seqId != "" {
   224  		id, err := strconv.Atoi(seqId)
   225  		if err != nil || id < 0 {
   226  			Response(c, http.StatusBadRequest, fmt.Errorf("id format error"), nil)
   227  			return
   228  		}
   229  		sq = r.Og.Dag.GetSequencerByHeight(uint64(id))
   230  		if sq != nil {
   231  			Response(c, http.StatusOK, nil, sq)
   232  			return
   233  		} else {
   234  			Response(c, http.StatusNotFound, fmt.Errorf("sequencer not found"), nil)
   235  			return
   236  		}
   237  	}
   238  	if hashtr == "" {
   239  		sq = r.Og.Dag.LatestSequencer()
   240  		if sq != nil {
   241  			Response(c, http.StatusOK, nil, sq)
   242  			return
   243  		} else {
   244  			Response(c, http.StatusNotFound, fmt.Errorf("sequencer not found"), nil)
   245  			return
   246  		}
   247  	} else {
   248  		hash, err := types2.HexToHash(hashtr)
   249  		if err != nil {
   250  			Response(c, http.StatusBadRequest, fmt.Errorf("hash format error"), nil)
   251  			return
   252  		}
   253  		txi := r.Og.Dag.GetTx(hash)
   254  		if txi == nil {
   255  			txi = r.Og.TxPool.Get(hash)
   256  		}
   257  		if txi == nil {
   258  			Response(c, http.StatusNotFound, fmt.Errorf("tx not found"), nil)
   259  			return
   260  		}
   261  		switch t := txi.(type) {
   262  		case *types.Sequencer:
   263  			Response(c, http.StatusOK, nil, t)
   264  			return
   265  		default:
   266  			Response(c, http.StatusNotFound, fmt.Errorf("tx not sequencer"), nil)
   267  			return
   268  		}
   269  	}
   270  	Response(c, http.StatusNotFound, fmt.Errorf("not found"), nil)
   271  	return
   272  }
   273  
   274  func (r *RpcController) NewAccount(c *gin.Context) {
   275  	var (
   276  		txReq  NewAccountRequest
   277  		signer og_interface.ISigner
   278  		err    error
   279  	)
   280  	err = c.ShouldBindJSON(&txReq)
   281  	if err != nil {
   282  		Response(c, http.StatusBadRequest, fmt.Errorf("request format error"), nil)
   283  		return
   284  	}
   285  	algorithm := strings.ToLower(txReq.Algorithm)
   286  	switch algorithm {
   287  	case "ed25519":
   288  		signer = &ogcrypto2.SignerEd25519{}
   289  	case "secp256k1":
   290  		signer = &ogcrypto2.SignerSecp256k1{}
   291  	}
   292  	pub, priv := signer.RandomKeyPair()
   293  	if err != nil {
   294  		Response(c, http.StatusInternalServerError, fmt.Errorf("Generate account error"), nil)
   295  		return
   296  	}
   297  	Response(c, http.StatusInternalServerError, nil, gin.H{
   298  		"pubkey":  pub.String(),
   299  		"privkey": priv.String(),
   300  	})
   301  	return
   302  }
   303  
   304  func (r *RpcController) QueryNonce(c *gin.Context) {
   305  	address := c.Query("address")
   306  	addr, err := common.StringToAddress(address)
   307  	if err != nil {
   308  		Response(c, http.StatusBadRequest, fmt.Errorf("address format err"), nil)
   309  		return
   310  	}
   311  	noncePool, errPool := r.Og.TxPool.GetLatestNonce(addr)
   312  	nonceDag, errDag := r.Og.Dag.GetLatestNonce(addr)
   313  	var nonce int64
   314  	if errPool != nil && errDag != nil {
   315  		nonce = 0
   316  	} else {
   317  		nonce = int64(noncePool)
   318  		if noncePool < nonceDag {
   319  			nonce = int64(nonceDag)
   320  		}
   321  	}
   322  	Response(c, http.StatusOK, nil, nonce)
   323  	return
   324  }
   325  
   326  func (r *RpcController) QueryBalance(c *gin.Context) {
   327  	address := c.Query("address")
   328  	tokenIDStr := c.Query("token_id")
   329  	all := c.Query("all")
   330  	addr, err := common.StringToAddress(address)
   331  	if err != nil {
   332  		Response(c, http.StatusBadRequest, fmt.Errorf("address format err: %v", err), nil)
   333  		return
   334  	}
   335  	var tokenID int32
   336  	if tokenIDStr == "" {
   337  		tokenID = token.OGTokenID
   338  	} else {
   339  		t, err := strconv.Atoi(tokenIDStr)
   340  		if err != nil {
   341  			Response(c, http.StatusBadRequest, fmt.Errorf("tokenID format err: %v", err), nil)
   342  			return
   343  		}
   344  		tokenID = int32(t)
   345  	}
   346  	if all == "true" {
   347  		b := r.Og.Dag.GetAllTokenBalance(addr)
   348  		Response(c, http.StatusOK, nil, gin.H{
   349  			"address": address,
   350  			"balance": b,
   351  		})
   352  		return
   353  	}
   354  
   355  	b := r.Og.Dag.GetBalance(addr, tokenID)
   356  	Response(c, http.StatusOK, nil, gin.H{
   357  		"address": address,
   358  		"balance": b,
   359  	})
   360  	return
   361  }
   362  
   363  func (r *RpcController) QueryShare(c *gin.Context) {
   364  	Response(c, http.StatusOK, nil, "not implemented yet")
   365  	return
   366  }
   367  
   368  func (r *RpcController) ContractPayload(c *gin.Context) {
   369  	Response(c, http.StatusOK, nil, "not implemented yet")
   370  	return
   371  }
   372  
   373  func (r *RpcController) ConStatus(c *gin.Context) {
   374  	cors(c)
   375  	if r.AnnSensus != nil {
   376  		Response(c, http.StatusOK, nil, r.AnnSensus.GetInfo())
   377  	} else {
   378  		Response(c, http.StatusOK, nil, nil)
   379  	}
   380  
   381  }
   382  
   383  func (r *RpcController) ConfirmStatus(c *gin.Context) {
   384  	cors(c)
   385  	Response(c, http.StatusOK, nil, r.Og.TxPool.GetConfirmStatus())
   386  }
   387  
   388  type ReceiptResponse struct {
   389  	TxHash          string      `json:"tx_hash"`
   390  	Status          int         `json:"status"`
   391  	Result          interface{} `json:"result"`
   392  	ContractAddress string      `json:"contract_address"`
   393  }
   394  
   395  func (r *RpcController) QueryReceipt(c *gin.Context) {
   396  	hashHex := c.Query("hash")
   397  
   398  	hashBytes := common.FromHex(hashHex)
   399  	if hashBytes == nil {
   400  		Response(c, http.StatusBadRequest, fmt.Errorf("hash not hex"), nil)
   401  		return
   402  	}
   403  	hash := types2.BytesToHash(hashBytes)
   404  	receipt := r.Og.Dag.GetReceipt(hash)
   405  	if receipt == nil {
   406  		Response(c, http.StatusNotFound, fmt.Errorf("can't find receipt"), nil)
   407  		return
   408  	}
   409  
   410  	rr := ReceiptResponse{}
   411  	rr.TxHash = receipt.TxHash.Hex()
   412  	rr.Status = int(receipt.Status)
   413  	rr.Result = receipt.ProcessResult
   414  	rr.ContractAddress = receipt.ContractAddress.Hex()
   415  
   416  	Response(c, http.StatusOK, nil, rr)
   417  	return
   418  }
   419  
   420  type NewQueryContractReq struct {
   421  	Address string `json:"address"`
   422  	Data    string `json:"data"`
   423  }
   424  
   425  func (r *RpcController) QueryContract(c *gin.Context) {
   426  	var (
   427  		reqdata NewQueryContractReq
   428  	)
   429  
   430  	err := c.ShouldBindJSON(&reqdata)
   431  	if err != nil {
   432  		Response(c, http.StatusBadRequest, fmt.Errorf("request format error: %v", err), nil)
   433  		return
   434  	}
   435  
   436  	addr, err := common.StringToAddress(reqdata.Address)
   437  	if err != nil {
   438  		Response(c, http.StatusBadRequest, err, nil)
   439  		return
   440  	}
   441  	query, err := hex.DecodeString(reqdata.Data)
   442  	if err != nil {
   443  		Response(c, http.StatusBadRequest, fmt.Errorf("can't decode data to bytes"), nil)
   444  		return
   445  	}
   446  
   447  	ret, err := r.Og.Dag.CallContract(addr, query)
   448  	if err != nil {
   449  		Response(c, http.StatusNotFound, fmt.Errorf("query contract error: %v", err), nil)
   450  		return
   451  	}
   452  
   453  	Response(c, http.StatusOK, nil, hex.EncodeToString(ret))
   454  	return
   455  }
   456  
   457  func checkError(err error, c *gin.Context, status int, message string) bool {
   458  	if err != nil {
   459  		c.JSON(status, gin.H{
   460  			"error": fmt.Sprintf("%s:%s", err.Error(), message),
   461  		})
   462  		return false
   463  	}
   464  	return true
   465  }
   466  
   467  func Response(c *gin.Context, status int, err error, data interface{}) {
   468  	var msg string
   469  	if err != nil {
   470  		msg = err.Error()
   471  	}
   472  	c.JSON(status, gin.H{
   473  		"message": msg,
   474  		"data":    data,
   475  	})
   476  }