mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-05 11:32:14 +00:00
rpc: give each call a dedicated Response struct, add basic test
This commit is contained in:
parent
87e1f76324
commit
d2724c9731
@ -144,6 +144,10 @@ func (n *Node) StartRpc() {
|
||||
rpc.StartHTTPServer()
|
||||
}
|
||||
|
||||
func (n *Node) Switch() *p2p.Switch {
|
||||
return n.sw
|
||||
}
|
||||
|
||||
func (n *Node) ConsensusState() *consensus.ConsensusState {
|
||||
return n.consensusState
|
||||
}
|
||||
|
@ -223,6 +223,10 @@ func (sw *Switch) StopPeerGracefully(peer *Peer) {
|
||||
sw.doRemovePeer(peer, nil)
|
||||
}
|
||||
|
||||
func (sw *Switch) GetChainId() string {
|
||||
return sw.chainId
|
||||
}
|
||||
|
||||
func (sw *Switch) SetChainId(hash []byte, network string) {
|
||||
sw.chainId = hex.EncodeToString(hash) + "-" + network
|
||||
}
|
||||
|
@ -8,16 +8,28 @@ import (
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {}
|
||||
|
||||
type ResponseGenPrivAccount struct {
|
||||
PrivAccount *account.PrivAccount
|
||||
}
|
||||
|
||||
func GenPrivAccountHandler(w http.ResponseWriter, r *http.Request) {
|
||||
privAccount := account.GenPrivAccount()
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
PrivAccount *account.PrivAccount
|
||||
}{privAccount})
|
||||
WriteAPIResponse(w, API_OK, ResponseGenPrivAccount{privAccount})
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {"address": string}
|
||||
|
||||
type ResponseGetAccount struct {
|
||||
Account *account.Account
|
||||
}
|
||||
|
||||
func GetAccountHandler(w http.ResponseWriter, r *http.Request) {
|
||||
addressStr := GetParam(r, "address")
|
||||
|
||||
@ -37,13 +49,18 @@ func GetAccountHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
Account *account.Account
|
||||
}{account_})
|
||||
WriteAPIResponse(w, API_OK, ResponseGetAccount{account_})
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {}
|
||||
|
||||
type ResponseListAccounts struct {
|
||||
BlockHeight uint
|
||||
Accounts []*account.Account
|
||||
}
|
||||
|
||||
func ListAccountsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var blockHeight uint
|
||||
var accounts []*account.Account
|
||||
@ -54,8 +71,5 @@ func ListAccountsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return false
|
||||
})
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
BlockHeight uint
|
||||
Accounts []*account.Account
|
||||
}{blockHeight, accounts})
|
||||
WriteAPIResponse(w, API_OK, ResponseListAccounts{blockHeight, accounts})
|
||||
}
|
||||
|
@ -7,6 +7,15 @@ import (
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {}
|
||||
|
||||
type ResponseBlockchainInfo struct {
|
||||
LastHeight uint
|
||||
BlockMetas []*types.BlockMeta
|
||||
}
|
||||
|
||||
func BlockchainInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
minHeight, _ := GetParamUint(r, "min_height")
|
||||
maxHeight, _ := GetParamUint(r, "max_height")
|
||||
@ -26,14 +35,18 @@ func BlockchainInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
blockMetas = append(blockMetas, blockMeta)
|
||||
}
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
LastHeight uint
|
||||
BlockMetas []*types.BlockMeta
|
||||
}{blockStore.Height(), blockMetas})
|
||||
WriteAPIResponse(w, API_OK, ResponseBlockchainInfo{blockStore.Height(), blockMetas})
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {"height": uint}
|
||||
|
||||
type ResponseGetBlock struct {
|
||||
BlockMeta *types.BlockMeta
|
||||
Block *types.Block
|
||||
}
|
||||
|
||||
func GetBlockHandler(w http.ResponseWriter, r *http.Request) {
|
||||
height, _ := GetParamUint(r, "height")
|
||||
if height == 0 {
|
||||
@ -48,8 +61,5 @@ func GetBlockHandler(w http.ResponseWriter, r *http.Request) {
|
||||
blockMeta := blockStore.LoadBlockMeta(height)
|
||||
block := blockStore.LoadBlock(height)
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
BlockMeta *types.BlockMeta
|
||||
Block *types.Block
|
||||
}{blockMeta, block})
|
||||
WriteAPIResponse(w, API_OK, ResponseGetBlock{blockMeta, block})
|
||||
}
|
||||
|
@ -10,6 +10,17 @@ import (
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {"tx": string}
|
||||
// Note: "tx" should be json encoded signed transaction
|
||||
|
||||
type ResponseBroadcastTx struct {
|
||||
TxHash []byte
|
||||
CreatesContract bool
|
||||
ContractAddr []byte
|
||||
}
|
||||
|
||||
func BroadcastTxHandler(w http.ResponseWriter, r *http.Request) {
|
||||
txJSON := GetParam(r, "tx")
|
||||
var err error
|
||||
@ -37,11 +48,7 @@ func BroadcastTxHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
TxHash []byte
|
||||
CreatesContract bool
|
||||
ContractAddr []byte
|
||||
}{txHash, createsContract, contractAddr})
|
||||
WriteAPIResponse(w, API_OK, ResponseBroadcastTx{txHash, createsContract, contractAddr})
|
||||
return
|
||||
}
|
||||
|
||||
|
54
rpc/net.go
54
rpc/net.go
@ -2,22 +2,47 @@ package rpc
|
||||
|
||||
import (
|
||||
"github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {}
|
||||
|
||||
type ResponseStatus struct {
|
||||
ChainId string
|
||||
LatestBlockHash []byte
|
||||
LatestBlockHeight uint
|
||||
LatestBlockTime int64 // nano
|
||||
Network string
|
||||
}
|
||||
|
||||
func StatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
genesisHash := blockStore.LoadBlockMeta(0).Hash
|
||||
genesisHash := p2pSwitch.GetChainId()
|
||||
latestHeight := blockStore.Height()
|
||||
latestBlockMeta := blockStore.LoadBlockMeta(latestHeight)
|
||||
latestBlockHash := latestBlockMeta.Hash
|
||||
latestBlockTime := latestBlockMeta.Header.Time.UnixNano()
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
GenesisHash []byte
|
||||
LatestBlockHash []byte
|
||||
LatestBlockHeight uint
|
||||
LatestBlockTime int64 // nano
|
||||
Network string
|
||||
}{genesisHash, latestBlockHash, latestHeight, latestBlockTime, config.App().GetString("Network")})
|
||||
var (
|
||||
latestBlockMeta *types.BlockMeta
|
||||
latestBlockHash []byte
|
||||
latestBlockTime int64
|
||||
)
|
||||
if latestHeight != 0 {
|
||||
latestBlockMeta = blockStore.LoadBlockMeta(latestHeight)
|
||||
latestBlockHash = latestBlockMeta.Hash
|
||||
latestBlockTime = latestBlockMeta.Header.Time.UnixNano()
|
||||
}
|
||||
|
||||
WriteAPIResponse(w, API_OK, ResponseStatus{genesisHash, latestBlockHash, latestHeight, latestBlockTime, config.App().GetString("Network")})
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {}
|
||||
|
||||
type ResponseNetInfo struct {
|
||||
NumPeers int
|
||||
Listening bool
|
||||
Network string
|
||||
}
|
||||
|
||||
func NetInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
@ -25,9 +50,6 @@ func NetInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
numPeers := o + i
|
||||
listening := p2pSwitch.IsListening()
|
||||
network := config.App().GetString("Network")
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
NumPeers int
|
||||
Listening bool
|
||||
Network string
|
||||
}{numPeers, listening, network})
|
||||
WriteAPIResponse(w, API_OK,
|
||||
ResponseNetInfo{numPeers, listening, network})
|
||||
}
|
||||
|
70
rpc/test/rpc_test.go
Normal file
70
rpc/test/rpc_test.go
Normal file
@ -0,0 +1,70 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/daemon"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/rpc"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
rpcAddr = "127.0.0.1:8089"
|
||||
requestAddr = "http://" + rpcAddr + "/"
|
||||
chainId string
|
||||
node *daemon.Node
|
||||
)
|
||||
|
||||
func newNode() {
|
||||
// Create & start node
|
||||
node = daemon.NewNode()
|
||||
l := p2p.NewDefaultListener("tcp", config.App().GetString("ListenAddr"), false)
|
||||
node.AddListener(l)
|
||||
node.Start()
|
||||
|
||||
// Run the RPC server.
|
||||
node.StartRpc()
|
||||
|
||||
// Sleep forever
|
||||
ch := make(chan struct{})
|
||||
<-ch
|
||||
}
|
||||
|
||||
func init() {
|
||||
app := config.App()
|
||||
app.Set("SeedNode", "")
|
||||
app.Set("DB.Backend", "memdb")
|
||||
app.Set("RPC.HTTP.ListenAddr", rpcAddr)
|
||||
config.SetApp(app)
|
||||
// start a node
|
||||
go newNode()
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
|
||||
func TestSayHello(t *testing.T) {
|
||||
resp, err := http.Get(requestAddr + "status")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var status struct {
|
||||
Status string
|
||||
Data rpc.ResponseStatus
|
||||
}
|
||||
err = json.Unmarshal(body, &status)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if status.Data.ChainId != node.Switch().GetChainId() {
|
||||
t.Fatal(fmt.Errorf("ChainId mismatch: got %s expected %s", status.Data.ChainId, node.Switch().GetChainId()))
|
||||
}
|
||||
}
|
11
rpc/txs.go
11
rpc/txs.go
@ -9,6 +9,15 @@ import (
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {"tx": string}
|
||||
// Note: "tx" should be json encoded unsigned transaction
|
||||
|
||||
type ResponseSignTx struct {
|
||||
types.Tx
|
||||
}
|
||||
|
||||
func SignTxHandler(w http.ResponseWriter, r *http.Request) {
|
||||
txStr := GetParam(r, "tx")
|
||||
privAccountsStr := GetParam(r, "privAccounts")
|
||||
@ -53,5 +62,5 @@ func SignTxHandler(w http.ResponseWriter, r *http.Request) {
|
||||
rebondTx.Signature = privAccounts[0].Sign(rebondTx).(account.SignatureEd25519)
|
||||
}
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct{ types.Tx }{tx})
|
||||
WriteAPIResponse(w, API_OK, ResponseSignTx{tx})
|
||||
}
|
||||
|
@ -6,6 +6,16 @@ import (
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Request: {}
|
||||
|
||||
type ResponseListValidators struct {
|
||||
BlockHeight uint
|
||||
BondedValidators []*sm.Validator
|
||||
UnbondingValidators []*sm.Validator
|
||||
}
|
||||
|
||||
func ListValidatorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var blockHeight uint
|
||||
var bondedValidators []*sm.Validator
|
||||
@ -22,9 +32,5 @@ func ListValidatorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return false
|
||||
})
|
||||
|
||||
WriteAPIResponse(w, API_OK, struct {
|
||||
BlockHeight uint
|
||||
BondedValidators []*sm.Validator
|
||||
UnbondingValidators []*sm.Validator
|
||||
}{blockHeight, bondedValidators, unbondingValidators})
|
||||
WriteAPIResponse(w, API_OK, ResponseListValidators{blockHeight, bondedValidators, unbondingValidators})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user