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 }