diff --git a/api/service/restclientsupport/puzzle_service.go b/api/service/restclientsupport/puzzle_service.go index 96e9e7249..31190d085 100644 --- a/api/service/restclientsupport/puzzle_service.go +++ b/api/service/restclientsupport/puzzle_service.go @@ -3,10 +3,11 @@ package restclientsupport import ( "encoding/json" "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/harmony-one/harmony/internal/utils" "net/http" "strconv" + + "github.com/ethereum/go-ethereum/common" + "github.com/harmony-one/harmony/internal/utils" ) // Play triggers play method of puzzle smart contract. @@ -32,7 +33,6 @@ func (s *Service) Play(w http.ResponseWriter, r *http.Request) { return } - if err := s.CreateTransactionForPlayMethod(key, amountInt); err != nil { utils.GetLogInstance().Error("puzzle-play, error", err) json.NewEncoder(w).Encode(res) @@ -68,3 +68,27 @@ func (s *Service) Payout(w http.ResponseWriter, r *http.Request) { res.Success = true json.NewEncoder(w).Encode(res) } + +// End triggers endGame of puzzle smart contract. +func (s *Service) End(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + address := r.FormValue("address") + + fmt.Println("Payout: address", address) + res := &Response{ + Success: false, + } + + if s.CreateTransactionForPayoutMethod == nil { + json.NewEncoder(w).Encode(res) + return + } + + if err := s.CreateTransactionForEndMethod(common.HexToAddress(address)); err != nil { + utils.GetLogInstance().Error("Payout error", err) + json.NewEncoder(w).Encode(res) + return + } + res.Success = true + json.NewEncoder(w).Encode(res) +} diff --git a/api/service/restclientsupport/service.go b/api/service/restclientsupport/service.go index f97840939..1da77d868 100644 --- a/api/service/restclientsupport/service.go +++ b/api/service/restclientsupport/service.go @@ -37,6 +37,7 @@ type Service struct { GetAccountBalance func(common.Address) (*big.Int, error) CreateTransactionForPlayMethod func(string, int64) error CreateTransactionForPayoutMethod func(common.Address, int, string) error + CreateTransactionForEndMethod func(common.Address) error } // New returns new client support service. @@ -46,7 +47,8 @@ func New( CreateTransactionForPickWinner func() error, CallFaucetContract func(common.Address) common.Hash, GetAccountBalance func(common.Address) (*big.Int, error), CreateTransactionForPlayMethod func(string, int64) error, - CreateTransactionForPayoutMethod func(common.Address, int, string) error) *Service { + CreateTransactionForPayoutMethod func(common.Address, int, string) error, + CreateTransactionForEndMethod func(common.Address) error) *Service { return &Service{ CreateTransactionForEnterMethod: CreateTransactionForEnterMethod, GetResult: GetResult, @@ -55,6 +57,7 @@ func New( GetAccountBalance: GetAccountBalance, CreateTransactionForPlayMethod: CreateTransactionForPlayMethod, CreateTransactionForPayoutMethod: CreateTransactionForPayoutMethod, + CreateTransactionForEndMethod: CreateTransactionForEndMethod, } } @@ -106,6 +109,10 @@ func (s *Service) Run() *http.Server { // Set up router for payout. s.router.Path("/payout").Queries("address", "{[0-9A-Fa-fx]*?}", "level", "{[0-9]*?}", "sequence", "{[A-Za-z]*?}").HandlerFunc(s.Payout).Methods("GET") s.router.Path("/payout").HandlerFunc(s.Payout) + + // Set up router for endgame. + s.router.Path("/end").Queries("address", "{[0-9A-Fa-fx]*?}").HandlerFunc(s.End).Methods("GET") + s.router.Path("/end").HandlerFunc(s.End) // Do serving now. utils.GetLogInstance().Info("Listening on ", "port: ", Port) server := &http.Server{Addr: addr, Handler: s.router} diff --git a/node/puzzle_contract.go b/node/puzzle_contract.go index 62cd2c610..e498efe18 100644 --- a/node/puzzle_contract.go +++ b/node/puzzle_contract.go @@ -18,8 +18,9 @@ import ( // Constants for puzzle. const ( - Play = "play" - Payout = "payout" + Play = "play" + Payout = "payout" + EndGame = "endGame" ) var OneEther = big.NewInt(params.Ether) @@ -145,3 +146,49 @@ func (node *Node) CreateTransactionForPayoutMethod(address common.Address, level utils.GetLogInstance().Error("Unable to call enter method", "error", err) return err } + +// CreateTransactionForEndMethod generates transaction for endGame method and add it into pending tx list. +func (node *Node) CreateTransactionForEndMethod(address common.Address) error { + var err error + toAddress := node.PuzzleContractAddress + + abi, err := abi.JSON(strings.NewReader(contracts.PuzzleABI)) + if err != nil { + utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) + return err + } + // add params for address payable player, uint8 new_level, steps string + fmt.Println("EndGame: address", address) + bytesData, err := abi.Pack(EndGame, address) + if err != nil { + utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) + return err + } + + key := node.PuzzleManagerPrivateKey + if key == nil { + return fmt.Errorf("PuzzleManagerPrivateKey is nil") + } + nonce := node.GetNonceOfAddress(crypto.PubkeyToAddress(key.PublicKey)) + Amount := big.NewInt(0) + tx := types.NewTransaction( + nonce, + toAddress, + node.NodeConfig.ShardID, + Amount, + params.TxGas*10, + nil, + bytesData, + ) + + if err != nil { + utils.GetLogInstance().Error("Failed to get private key", "error", err) + return err + } + if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key); err == nil { + node.addPendingTransactions(types.Transactions{signedTx}) + return nil + } + utils.GetLogInstance().Error("Unable to call enter method", "error", err) + return err +} diff --git a/node/service_setup.go b/node/service_setup.go index ccf7523e5..7c112ee30 100644 --- a/node/service_setup.go +++ b/node/service_setup.go @@ -28,7 +28,7 @@ func (node *Node) setupForShardLeader() { node.serviceManager.RegisterService(service.RestClientSupport, restclientsupport.New( node.CreateTransactionForEnterMethod, node.GetResult, node.CreateTransactionForPickWinner, node.CallFaucetContract, node.GetBalanceOfAddress, - node.CreateTransactionForPlayMethod, node.CreateTransactionForPayoutMethod)) + node.CreateTransactionForPlayMethod, node.CreateTransactionForPayoutMethod, node.CreateTransactionForEndMethod)) // Register explorer service. node.serviceManager.RegisterService(service.SupportExplorer, explorer.New(&node.SelfPeer, node.Consensus.GetNodeIDs, node.GetBalanceOfAddress)) @@ -70,7 +70,7 @@ func (node *Node) setupForBeaconLeader() { node.serviceManager.RegisterService(service.RestClientSupport, restclientsupport.New( node.CreateTransactionForEnterMethod, node.GetResult, node.CreateTransactionForPickWinner, node.CallFaucetContract, node.GetBalanceOfAddress, - node.CreateTransactionForPlayMethod, node.CreateTransactionForPayoutMethod)) + node.CreateTransactionForPlayMethod, node.CreateTransactionForPayoutMethod, node.CreateTransactionForEndMethod)) // Register randomness service node.serviceManager.RegisterService(service.Randomness, randomness.New(node.DRand)) // Register explorer service.