Commit 85079a64 authored by 贾浩@五瓣科技's avatar 贾浩@五瓣科技

Merge branch 'dev_2step_login'

# Conflicts:
#	gassender/gassender.go
#	server/router.go
parents db412351 cbc54ced
...@@ -15,7 +15,7 @@ listen = "0.0.0.0:8080" ...@@ -15,7 +15,7 @@ listen = "0.0.0.0:8080"
[gas_sender] [gas_sender]
rpc = "https://sepolia.rpc.aonnet.io" rpc = "https://sepolia.rpc.aonnet.io"
user_contract = "0x64ea0CC733f9B899545aE454f1890b5eb512560F"
# 0x0000000077024042e797Ae28A163C27E389CC5b2 # 0x0000000077024042e797Ae28A163C27E389CC5b2
private_key = "39494cd233573c94d6b4d24847f2f4d5da9d0b384b61f3ad4fae9abd5c48e6fc" private_key = "39494cd233573c94d6b4d24847f2f4d5da9d0b384b61f3ad4fae9abd5c48e6fc"
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
...@@ -20,15 +21,16 @@ type GasSender struct { ...@@ -20,15 +21,16 @@ type GasSender struct {
client *ethclient.Client client *ethclient.Client
taskCh chan *gasTask taskCh chan *gasTask
chainId *big.Int chainId *big.Int
nonce uint64
aonUser *aonUser.AonUser aonUser *aonUser.AonUser
} }
type gasTask struct { type gasTask struct {
user common.Address dest common.Address
userId string user common.Address
inviter string value *big.Int
nonce uint64 userId string
inviterId string
method string
} }
func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) { func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) {
...@@ -37,6 +39,8 @@ func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) { ...@@ -37,6 +39,8 @@ func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) {
return nil, err return nil, err
} }
log.WithField("address", crypto.PubkeyToAddress(ecdsaKey.PublicKey)).Info("aon gas sender address")
client, err := ethclient.Dial(rpc) client, err := ethclient.Dial(rpc)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -47,11 +51,6 @@ func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) { ...@@ -47,11 +51,6 @@ func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) {
return nil, err return nil, err
} }
nonce, err := client.NonceAt(context.Background(), crypto.PubkeyToAddress(ecdsaKey.PublicKey), nil)
if err != nil {
return nil, err
}
ca, err := aonUser.NewAonUser(common.HexToAddress(aonUserContract), client) ca, err := aonUser.NewAonUser(common.HexToAddress(aonUserContract), client)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -60,15 +59,13 @@ func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) { ...@@ -60,15 +59,13 @@ func NewGasSender(rpc, privateKey, aonUserContract string) (*GasSender, error) {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"caller": crypto.PubkeyToAddress(ecdsaKey.PublicKey), "caller": crypto.PubkeyToAddress(ecdsaKey.PublicKey),
"userContract": common.HexToAddress(aonUserContract), "userContract": common.HexToAddress(aonUserContract),
"nonce": nonce,
}).Info("init gas sender") }).Info("init gas sender")
return &GasSender{ return &GasSender{
privateKey: ecdsaKey, privateKey: ecdsaKey,
client: client, client: client,
taskCh: make(chan *gasTask, 64), taskCh: make(chan *gasTask, 32),
chainId: chainId, chainId: chainId,
nonce: nonce,
aonUser: ca, aonUser: ca,
}, nil }, nil
...@@ -79,37 +76,98 @@ func (gs *GasSender) Run() { ...@@ -79,37 +76,98 @@ func (gs *GasSender) Run() {
for { for {
select { select {
case task := <-gs.taskCh: case task := <-gs.taskCh:
task.nonce = gs.nonce switch task.method {
gs.nonce++ case "sendGas":
go gs.sendTx(task) gs.sendGas(task)
case "aonLogin":
gs.login(task)
}
} }
} }
}() }()
} }
// func (gs *GasSender) SendAONGas(dest string, amount int) { func (gs *GasSender) SendAONGas(dest string, amount int) {
// addr := common.HexToAddress(dest) addr := common.HexToAddress(dest)
// value := new(big.Int).Mul(big.NewInt(int64(amount)), big.NewInt(1000000000000000000)) value := new(big.Int).Mul(big.NewInt(int64(amount)), big.NewInt(1000000000000000000))
// gs.taskCh <- &gasTask{ gs.taskCh <- &gasTask{
// dest: addr, dest: addr,
// value: value, value: value,
// } method: "sendGas",
// } }
}
func (gs *GasSender) AonLogin(user common.Address, userId, inviter string) { func (gs *GasSender) AonLogin(address common.Address, userId, inviter string) {
gs.taskCh <- &gasTask{ gs.taskCh <- &gasTask{
user: user, user: address,
userId: userId, value: big.NewInt(0),
inviter: inviter, userId: userId,
inviterId: inviter,
method: "aonLogin",
}
}
func (gs *GasSender) sendGas(task *gasTask) {
log.WithFields(log.Fields{
"address": task.dest,
"value": task.value,
}).Info("new send gas task")
nonce, err := gs.client.NonceAt(context.Background(), crypto.PubkeyToAddress(gs.privateKey.PublicKey), nil)
if err != nil {
log.WithError(err).Error("get nonce failed")
return
}
tx := &types.LegacyTx{
Nonce: nonce,
GasPrice: big.NewInt(1000000000),
Gas: 21000,
To: &task.dest,
Value: task.value,
}
signer := types.NewEIP155Signer(gs.chainId)
signedTx, err := types.SignNewTx(gs.privateKey, signer, tx)
if err != nil {
log.WithError(err).Error("sign tx failed")
return
}
err = gs.client.SendTransaction(context.Background(), signedTx)
if err != nil {
log.WithError(err).Error("send tx failed")
return
}
txLog := log.WithField("txHash", signedTx.Hash().Hex())
txLog.Info("tx broadcasted")
for i := 0; i < 5; i++ {
time.Sleep(time.Second * 2)
receipt, err := gs.client.TransactionReceipt(context.Background(), signedTx.Hash())
if err != nil && err == ethereum.NotFound {
txLog.Info("tx receipt not found, retrying...")
continue
}
if err != nil {
txLog.WithError(err).Error("send gas tx failed")
return
}
if receipt.Status != 1 {
txLog.Error("send gas tx failed")
return
}
txLog.Info("send gas tx confirmed")
return
} }
txLog.Error("tx receipt not found, timeout")
} }
func (gs *GasSender) sendTx(task *gasTask) { func (gs *GasSender) login(task *gasTask) {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"address": task.user.Hex(), "address": task.user.Hex(),
"userId": task.userId, "userId": task.userId,
"inviterId": task.inviter, "inviterId": task.inviterId,
"nonce": task.nonce,
}).Info("new login task") }).Info("new login task")
opts, err := bind.NewKeyedTransactorWithChainID(gs.privateKey, gs.chainId) opts, err := bind.NewKeyedTransactorWithChainID(gs.privateKey, gs.chainId)
...@@ -119,10 +177,9 @@ func (gs *GasSender) sendTx(task *gasTask) { ...@@ -119,10 +177,9 @@ func (gs *GasSender) sendTx(task *gasTask) {
} }
opts.GasPrice = big.NewInt(1000000000) opts.GasPrice = big.NewInt(1000000000)
opts.GasLimit = 5000000 opts.GasLimit = 2000000
opts.Nonce = big.NewInt(int64(task.nonce))
signedTx, err := gs.aonUser.LoginByServer(opts, task.user, task.userId, task.inviter) signedTx, err := gs.aonUser.LoginByServer(opts, task.user, task.userId, task.inviterId)
if err != nil { if err != nil {
log.WithError(err).Error("send tx failed") log.WithError(err).Error("send tx failed")
return return
......
...@@ -23,3 +23,13 @@ type CreateUserRequest struct { ...@@ -23,3 +23,13 @@ type CreateUserRequest struct {
type CreateUserResponse struct { type CreateUserResponse struct {
} }
type LoginRequest struct {
InitData string `json:"initData"`
Platform string `json:"platform"`
VisitorID string `json:"visitorId"`
Keystore string `json:"keystore"`
Signature string `json:"signature"`
UserId string `json:"userId"`
InviterId string `json:"inviter_id"`
}
...@@ -14,7 +14,8 @@ func initRouter(e *gin.Engine) { ...@@ -14,7 +14,8 @@ func initRouter(e *gin.Engine) {
{ {
user := v1.Group("/user") user := v1.Group("/user")
user.POST("/check", checkUser) user.POST("/check", checkUser)
// user.POST("/create", middleware.JWTMiddleware, createUser) user.POST("/serverLogin", login)
user.POST("/create", middleware.JWTMiddleware, createUser)
} }
} }
...@@ -134,3 +134,83 @@ func createUser(c *gin.Context) { ...@@ -134,3 +134,83 @@ func createUser(c *gin.Context) {
} }
c.JSON(200, withSuccess("")) c.JSON(200, withSuccess(""))
} }
func login(c *gin.Context) {
req := &apiModel.LoginRequest{}
if err := c.ShouldBindJSON(req); err != nil {
c.JSON(200, withError(constant.InvalidParam))
return
}
var platformId string
switch req.Platform {
case constant.PlatformTelegram:
var ok bool
var userId string
var botId string
for _, token := range conf.TGBot.Tokens {
ok, botId, userId = util.VerifyInitData(req.InitData, token)
if ok {
break
}
}
if !ok {
c.JSON(200, withError("invalid initData"))
return
}
platformId = fmt.Sprintf("%s:%s", botId, userId)
case constant.PlatformFingerprint:
if len(req.VisitorID) <= 10 {
c.JSON(200, withError(constant.InvalidParam))
return
}
platformId = req.VisitorID
default:
c.JSON(200, withError(constant.UnsupportedPlatform))
return
}
// 检查签名是否为keystore中的地址
address := gjson.Get(req.Keystore, "address").String()
binSignature, err := hexutil.Decode(req.Signature)
if err != nil || len(binSignature) < 65 {
c.JSON(200, withError("invalid signature"))
return
}
binSignature[64] -= 27
ecdsaPub, err := crypto.SigToPub(accounts.TextHash([]byte(req.Keystore)), binSignature)
if err != nil {
c.JSON(200, withError("invalid signature"))
return
}
addr := crypto.PubkeyToAddress(*ecdsaPub)
if strings.ToLower(addr.Hex()[2:]) != address {
c.JSON(200, withError("invalid signature"))
return
}
isExistKeystore, uid, keystore, err := srv.CheckUser(req.Platform, platformId)
if err != nil {
c.JSON(200, withError(constant.InternalError))
return
}
token := util.GenerateJWT(uid, req.Platform, platformId)
resp := &apiModel.CheckUserResponse{
IsNewUser: !isExistKeystore,
Keystore: keystore,
Token: token,
}
if !isExistKeystore {
_, err = srv.SetKeystore(uid, address, req.Keystore)
if err != nil {
c.JSON(200, withError(constant.InternalError))
return
}
resp.Keystore = req.Keystore
}
srv.AONServerLogin(address, req.UserId, req.InviterId)
c.JSON(200, withSuccess(resp))
return
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment