mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-06 03:52:15 +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()
|
rpc.StartHTTPServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Node) Switch() *p2p.Switch {
|
||||||
|
return n.sw
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Node) ConsensusState() *consensus.ConsensusState {
|
func (n *Node) ConsensusState() *consensus.ConsensusState {
|
||||||
return n.consensusState
|
return n.consensusState
|
||||||
}
|
}
|
||||||
|
@ -223,6 +223,10 @@ func (sw *Switch) StopPeerGracefully(peer *Peer) {
|
|||||||
sw.doRemovePeer(peer, nil)
|
sw.doRemovePeer(peer, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sw *Switch) GetChainId() string {
|
||||||
|
return sw.chainId
|
||||||
|
}
|
||||||
|
|
||||||
func (sw *Switch) SetChainId(hash []byte, network string) {
|
func (sw *Switch) SetChainId(hash []byte, network string) {
|
||||||
sw.chainId = hex.EncodeToString(hash) + "-" + network
|
sw.chainId = hex.EncodeToString(hash) + "-" + network
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,28 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Request: {}
|
||||||
|
|
||||||
|
type ResponseGenPrivAccount struct {
|
||||||
|
PrivAccount *account.PrivAccount
|
||||||
|
}
|
||||||
|
|
||||||
func GenPrivAccountHandler(w http.ResponseWriter, r *http.Request) {
|
func GenPrivAccountHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
privAccount := account.GenPrivAccount()
|
privAccount := account.GenPrivAccount()
|
||||||
|
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK, ResponseGenPrivAccount{privAccount})
|
||||||
PrivAccount *account.PrivAccount
|
|
||||||
}{privAccount})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Request: {"address": string}
|
||||||
|
|
||||||
|
type ResponseGetAccount struct {
|
||||||
|
Account *account.Account
|
||||||
|
}
|
||||||
|
|
||||||
func GetAccountHandler(w http.ResponseWriter, r *http.Request) {
|
func GetAccountHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
addressStr := GetParam(r, "address")
|
addressStr := GetParam(r, "address")
|
||||||
|
|
||||||
@ -37,13 +49,18 @@ func GetAccountHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK, ResponseGetAccount{account_})
|
||||||
Account *account.Account
|
|
||||||
}{account_})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Request: {}
|
||||||
|
|
||||||
|
type ResponseListAccounts struct {
|
||||||
|
BlockHeight uint
|
||||||
|
Accounts []*account.Account
|
||||||
|
}
|
||||||
|
|
||||||
func ListAccountsHandler(w http.ResponseWriter, r *http.Request) {
|
func ListAccountsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var blockHeight uint
|
var blockHeight uint
|
||||||
var accounts []*account.Account
|
var accounts []*account.Account
|
||||||
@ -54,8 +71,5 @@ func ListAccountsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK, ResponseListAccounts{blockHeight, accounts})
|
||||||
BlockHeight uint
|
|
||||||
Accounts []*account.Account
|
|
||||||
}{blockHeight, accounts})
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,15 @@ import (
|
|||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Request: {}
|
||||||
|
|
||||||
|
type ResponseBlockchainInfo struct {
|
||||||
|
LastHeight uint
|
||||||
|
BlockMetas []*types.BlockMeta
|
||||||
|
}
|
||||||
|
|
||||||
func BlockchainInfoHandler(w http.ResponseWriter, r *http.Request) {
|
func BlockchainInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
minHeight, _ := GetParamUint(r, "min_height")
|
minHeight, _ := GetParamUint(r, "min_height")
|
||||||
maxHeight, _ := GetParamUint(r, "max_height")
|
maxHeight, _ := GetParamUint(r, "max_height")
|
||||||
@ -26,14 +35,18 @@ func BlockchainInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
blockMetas = append(blockMetas, blockMeta)
|
blockMetas = append(blockMetas, blockMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK, ResponseBlockchainInfo{blockStore.Height(), blockMetas})
|
||||||
LastHeight uint
|
|
||||||
BlockMetas []*types.BlockMeta
|
|
||||||
}{blockStore.Height(), blockMetas})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Request: {"height": uint}
|
||||||
|
|
||||||
|
type ResponseGetBlock struct {
|
||||||
|
BlockMeta *types.BlockMeta
|
||||||
|
Block *types.Block
|
||||||
|
}
|
||||||
|
|
||||||
func GetBlockHandler(w http.ResponseWriter, r *http.Request) {
|
func GetBlockHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
height, _ := GetParamUint(r, "height")
|
height, _ := GetParamUint(r, "height")
|
||||||
if height == 0 {
|
if height == 0 {
|
||||||
@ -48,8 +61,5 @@ func GetBlockHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
blockMeta := blockStore.LoadBlockMeta(height)
|
blockMeta := blockStore.LoadBlockMeta(height)
|
||||||
block := blockStore.LoadBlock(height)
|
block := blockStore.LoadBlock(height)
|
||||||
|
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK, ResponseGetBlock{blockMeta, block})
|
||||||
BlockMeta *types.BlockMeta
|
|
||||||
Block *types.Block
|
|
||||||
}{blockMeta, block})
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,17 @@ import (
|
|||||||
"github.com/tendermint/tendermint/types"
|
"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) {
|
func BroadcastTxHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
txJSON := GetParam(r, "tx")
|
txJSON := GetParam(r, "tx")
|
||||||
var err error
|
var err error
|
||||||
@ -37,11 +48,7 @@ func BroadcastTxHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK, ResponseBroadcastTx{txHash, createsContract, contractAddr})
|
||||||
TxHash []byte
|
|
||||||
CreatesContract bool
|
|
||||||
ContractAddr []byte
|
|
||||||
}{txHash, createsContract, contractAddr})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
54
rpc/net.go
54
rpc/net.go
@ -2,22 +2,47 @@ package rpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/tendermint/config"
|
"github.com/tendermint/tendermint/config"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
"net/http"
|
"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) {
|
func StatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
genesisHash := blockStore.LoadBlockMeta(0).Hash
|
genesisHash := p2pSwitch.GetChainId()
|
||||||
latestHeight := blockStore.Height()
|
latestHeight := blockStore.Height()
|
||||||
latestBlockMeta := blockStore.LoadBlockMeta(latestHeight)
|
var (
|
||||||
latestBlockHash := latestBlockMeta.Hash
|
latestBlockMeta *types.BlockMeta
|
||||||
latestBlockTime := latestBlockMeta.Header.Time.UnixNano()
|
latestBlockHash []byte
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
latestBlockTime int64
|
||||||
GenesisHash []byte
|
)
|
||||||
LatestBlockHash []byte
|
if latestHeight != 0 {
|
||||||
LatestBlockHeight uint
|
latestBlockMeta = blockStore.LoadBlockMeta(latestHeight)
|
||||||
LatestBlockTime int64 // nano
|
latestBlockHash = latestBlockMeta.Hash
|
||||||
Network string
|
latestBlockTime = latestBlockMeta.Header.Time.UnixNano()
|
||||||
}{genesisHash, latestBlockHash, latestHeight, latestBlockTime, config.App().GetString("Network")})
|
}
|
||||||
|
|
||||||
|
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) {
|
func NetInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -25,9 +50,6 @@ func NetInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
numPeers := o + i
|
numPeers := o + i
|
||||||
listening := p2pSwitch.IsListening()
|
listening := p2pSwitch.IsListening()
|
||||||
network := config.App().GetString("Network")
|
network := config.App().GetString("Network")
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK,
|
||||||
NumPeers int
|
ResponseNetInfo{numPeers, listening, network})
|
||||||
Listening bool
|
|
||||||
Network string
|
|
||||||
}{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"
|
"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) {
|
func SignTxHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
txStr := GetParam(r, "tx")
|
txStr := GetParam(r, "tx")
|
||||||
privAccountsStr := GetParam(r, "privAccounts")
|
privAccountsStr := GetParam(r, "privAccounts")
|
||||||
@ -53,5 +62,5 @@ func SignTxHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
rebondTx.Signature = privAccounts[0].Sign(rebondTx).(account.SignatureEd25519)
|
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"
|
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) {
|
func ListValidatorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var blockHeight uint
|
var blockHeight uint
|
||||||
var bondedValidators []*sm.Validator
|
var bondedValidators []*sm.Validator
|
||||||
@ -22,9 +32,5 @@ func ListValidatorsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
WriteAPIResponse(w, API_OK, struct {
|
WriteAPIResponse(w, API_OK, ResponseListValidators{blockHeight, bondedValidators, unbondingValidators})
|
||||||
BlockHeight uint
|
|
||||||
BondedValidators []*sm.Validator
|
|
||||||
UnbondingValidators []*sm.Validator
|
|
||||||
}{blockHeight, bondedValidators, unbondingValidators})
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user