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 }