107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
package grpc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/meshplus/bitxhub-kit/types"
|
|
"github.com/meshplus/bitxhub-model/pb"
|
|
)
|
|
|
|
// SendTransaction handles transaction sent by the client.
|
|
// If the transaction is valid, it will return the transaction hash.
|
|
func (cbs *ChainBrokerService) SendTransaction(ctx context.Context, tx *pb.SendTransactionRequest) (*pb.TransactionHashMsg, error) {
|
|
if !cbs.api.Broker().OrderReady() {
|
|
return nil, fmt.Errorf("the system is temporarily unavailable")
|
|
}
|
|
|
|
if err := cbs.checkTransaction(tx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
hash, err := cbs.sendTransaction(tx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &pb.TransactionHashMsg{TxHash: hash}, nil
|
|
}
|
|
|
|
func (cbs *ChainBrokerService) checkTransaction(tx *pb.SendTransactionRequest) error {
|
|
if tx.Data == nil {
|
|
return fmt.Errorf("tx data can't be empty")
|
|
}
|
|
|
|
if tx.Data.Type == pb.TransactionData_NORMAL && tx.Data.Amount == 0 {
|
|
return fmt.Errorf("amount can't be 0 in transfer tx")
|
|
}
|
|
|
|
emptyAddress := types.Address{}.Hex()
|
|
if tx.From.Hex() == emptyAddress {
|
|
return fmt.Errorf("from can't be empty")
|
|
}
|
|
|
|
if tx.From == tx.To {
|
|
return fmt.Errorf("from can`t be the same as to")
|
|
}
|
|
|
|
if tx.To.Hex() == emptyAddress && len(tx.Data.Payload) == 0 {
|
|
return fmt.Errorf("can't deploy empty contract")
|
|
}
|
|
|
|
if tx.Timestamp < time.Now().UnixNano()-10*time.Minute.Nanoseconds() ||
|
|
tx.Timestamp > time.Now().UnixNano()+10*time.Minute.Nanoseconds() {
|
|
return fmt.Errorf("timestamp is illegal")
|
|
}
|
|
|
|
if tx.Nonce <= 0 {
|
|
return fmt.Errorf("nonce is illegal")
|
|
}
|
|
|
|
if len(tx.Signature) == 0 {
|
|
return fmt.Errorf("signature can't be empty")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (cbs *ChainBrokerService) sendTransaction(req *pb.SendTransactionRequest) (string, error) {
|
|
tx := &pb.Transaction{
|
|
Version: req.Version,
|
|
From: req.From,
|
|
To: req.To,
|
|
Timestamp: req.Timestamp,
|
|
Data: req.Data,
|
|
Nonce: req.Nonce,
|
|
Signature: req.Signature,
|
|
Extra: req.Extra,
|
|
}
|
|
|
|
tx.TransactionHash = tx.Hash()
|
|
err := cbs.api.Broker().HandleTransaction(tx)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return tx.TransactionHash.Hex(), nil
|
|
}
|
|
|
|
func (cbs *ChainBrokerService) GetTransaction(ctx context.Context, req *pb.TransactionHashMsg) (*pb.GetTransactionResponse, error) {
|
|
hash := types.String2Hash(req.TxHash)
|
|
tx, err := cbs.api.Broker().GetTransaction(hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
meta, err := cbs.api.Broker().GetTransactionMeta(hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &pb.GetTransactionResponse{
|
|
Tx: tx,
|
|
TxMeta: meta,
|
|
}, nil
|
|
}
|