@ -1,75 +0,0 @@ | |||
package rpc | |||
import ( | |||
"net/http" | |||
"github.com/tendermint/tendermint/account" | |||
"github.com/tendermint/tendermint/binary" | |||
. "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, ResponseGenPrivAccount{privAccount}) | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Request: {"address": string} | |||
type ResponseGetAccount struct { | |||
Account *account.Account | |||
} | |||
func GetAccountHandler(w http.ResponseWriter, r *http.Request) { | |||
addressStr := GetParam(r, "address") | |||
var address []byte | |||
var err error | |||
binary.ReadJSON(&address, []byte(addressStr), &err) | |||
if err != nil { | |||
WriteAPIResponse(w, API_INVALID_PARAM, Fmt("Invalid address: %v", err)) | |||
return | |||
} | |||
state := consensusState.GetState() | |||
account_ := state.GetAccount(address) | |||
if account_ == nil { | |||
WriteAPIResponse(w, API_OK, struct{}{}) | |||
return | |||
} | |||
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 | |||
state := consensusState.GetState() | |||
blockHeight = state.LastBlockHeight | |||
state.GetAccounts().Iterate(func(key interface{}, value interface{}) bool { | |||
accounts = append(accounts, value.(*account.Account)) | |||
return false | |||
}) | |||
WriteAPIResponse(w, API_OK, ResponseListAccounts{blockHeight, accounts}) | |||
} |
@ -1,65 +0,0 @@ | |||
package rpc | |||
import ( | |||
"net/http" | |||
. "github.com/tendermint/tendermint/common" | |||
"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") | |||
if maxHeight == 0 { | |||
maxHeight = blockStore.Height() | |||
} else { | |||
maxHeight = MinUint(blockStore.Height(), maxHeight) | |||
} | |||
if minHeight == 0 { | |||
minHeight = uint(MaxInt(1, int(maxHeight)-20)) | |||
} | |||
log.Debug("BlockchainInfoHandler", "maxHeight", maxHeight, "minHeight", minHeight) | |||
blockMetas := []*types.BlockMeta{} | |||
for height := maxHeight; height >= minHeight; height-- { | |||
blockMeta := blockStore.LoadBlockMeta(height) | |||
blockMetas = append(blockMetas, blockMeta) | |||
} | |||
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 { | |||
WriteAPIResponse(w, API_INVALID_PARAM, "height must be greater than 1") | |||
return | |||
} | |||
if height > blockStore.Height() { | |||
WriteAPIResponse(w, API_INVALID_PARAM, "height must be less than the current blockchain height") | |||
return | |||
} | |||
blockMeta := blockStore.LoadBlockMeta(height) | |||
block := blockStore.LoadBlock(height) | |||
WriteAPIResponse(w, API_OK, ResponseGetBlock{blockMeta, block}) | |||
} |
@ -1,21 +1,245 @@ | |||
package rpc | |||
import ( | |||
"encoding/json" | |||
"fmt" | |||
"github.com/tendermint/tendermint/binary" | |||
"github.com/tendermint/tendermint/rpc/core" | |||
"io/ioutil" | |||
"net/http" | |||
"reflect" | |||
"strconv" | |||
) | |||
// map each function to the argument names | |||
var argsMap = map[string][]string{ | |||
"status": []string{}, | |||
"net_info": []string{}, | |||
"blockchain": []string{"min_height", "max_height"}, | |||
"get_block": []string{"height"}, | |||
"get_account": []string{"address"}, | |||
"list_validators": []string{}, | |||
"broadcast_tx": []string{"tx"}, | |||
"list_accounts": []string{}, | |||
"gen_priv_account": []string{}, | |||
"sign_tx": []string{"tx", "privAccounts"}, | |||
} | |||
// cache all type information about each function up front | |||
var funcMap = map[string]*FuncWrapper{ | |||
"status": funcWrap("status", core.Status), | |||
"net_info": funcWrap("net_info", core.NetInfo), | |||
"blockchain": funcWrap("blockchain", core.BlockchainInfo), | |||
"get_block": funcWrap("get_block", core.GetBlock), | |||
"get_account": funcWrap("get_account", core.GetAccount), | |||
"list_validators": funcWrap("list_validators", core.ListValidators), | |||
"broadcast_tx": funcWrap("broadcast_tx", core.BroadcastTx), | |||
"list_accounts": funcWrap("list_accounts", core.ListAccounts), | |||
"gen_priv_account": funcWrap("gen_priv_account", core.GenPrivAccount), | |||
"sign_tx": funcWrap("sign_tx", core.SignTx), | |||
} | |||
var responseMap = map[string]reflect.Value{ | |||
"status": reflect.ValueOf(&ResponseStatus{}), | |||
"net_info": reflect.ValueOf(&ResponseNetInfo{}), | |||
"blockchain": reflect.ValueOf(&ResponseBlockchainInfo{}), | |||
"get_block": reflect.ValueOf(&ResponseGetBlock{}), | |||
"get_account": reflect.ValueOf(&ResponseGetAccount{}), | |||
"list_validators": reflect.ValueOf(&ResponseListValidators{}), | |||
"broadcast_tx": reflect.ValueOf(&ResponseBroadcastTx{}), | |||
"list_accounts": reflect.ValueOf(&ResponseListAccounts{}), | |||
"gen_priv_account": reflect.ValueOf(&ResponseGenPrivAccount{}), | |||
"sign_tx": reflect.ValueOf(&ResponseSignTx{}), | |||
} | |||
type FuncWrapper struct { | |||
f reflect.Value // function from "rpc/core" | |||
args []reflect.Type // type of each function arg | |||
returns []reflect.Type // type of each return arg | |||
argNames []string // name of each argument | |||
response reflect.Value // response struct (to be filled with "returns") | |||
} | |||
func funcWrap(name string, f interface{}) *FuncWrapper { | |||
return &FuncWrapper{ | |||
f: reflect.ValueOf(f), | |||
args: funcArgTypes(f), | |||
returns: funcReturnTypes(f), | |||
argNames: argsMap[name], | |||
response: responseMap[name], | |||
} | |||
} | |||
// convert from a function name to the http handler | |||
func toHandler(funcName string) func(http.ResponseWriter, *http.Request) { | |||
funcInfo := funcMap[funcName] | |||
return func(w http.ResponseWriter, r *http.Request) { | |||
values, err := queryToValues(funcInfo, r) | |||
if err != nil { | |||
WriteAPIResponse(w, API_INVALID_PARAM, err.Error()) | |||
return | |||
} | |||
returns := funcInfo.f.Call(values) | |||
response, err := returnsToResponse(funcInfo, returns) | |||
if err != nil { | |||
WriteAPIResponse(w, API_ERROR, err.Error()) | |||
} | |||
WriteAPIResponse(w, API_OK, response) | |||
} | |||
} | |||
// covert an http query to a list of properly typed values | |||
func queryToValues(funcInfo *FuncWrapper, r *http.Request) ([]reflect.Value, error) { | |||
argTypes := funcInfo.args | |||
argNames := funcInfo.argNames | |||
var err error | |||
values := make([]reflect.Value, len(argNames)) | |||
fmt.Println("names:", argNames) | |||
for i, name := range argNames { | |||
ty := argTypes[i] | |||
v := reflect.New(ty).Elem() | |||
kind := v.Kind() | |||
arg := GetParam(r, name) | |||
switch kind { | |||
case reflect.Struct: | |||
binary.ReadJSON(v.Interface(), []byte(arg), &err) | |||
if err != nil { | |||
return nil, err | |||
} | |||
case reflect.Slice: | |||
v = reflect.ValueOf([]byte(arg)) | |||
case reflect.Int64: | |||
u, err := strconv.ParseInt(arg, 10, 64) | |||
if err != nil { | |||
return nil, err | |||
} | |||
v = reflect.ValueOf(u) | |||
case reflect.Int32: | |||
u, err := strconv.ParseInt(arg, 10, 32) | |||
if err != nil { | |||
return nil, err | |||
} | |||
v = reflect.ValueOf(u) | |||
case reflect.Uint64: | |||
u, err := strconv.ParseUint(arg, 10, 64) | |||
if err != nil { | |||
return nil, err | |||
} | |||
v = reflect.ValueOf(u) | |||
case reflect.Uint: | |||
u, err := strconv.ParseUint(arg, 10, 32) | |||
if err != nil { | |||
return nil, err | |||
} | |||
v = reflect.ValueOf(u) | |||
default: | |||
v = reflect.ValueOf(arg) | |||
} | |||
values[i] = v | |||
} | |||
return values, nil | |||
} | |||
// covert a list of interfaces to properly typed values | |||
func paramsToValues(funcInfo *FuncWrapper, params []interface{}) ([]reflect.Value, error) { | |||
values := make([]reflect.Value, len(params)) | |||
for i, p := range params { | |||
values[i] = reflect.ValueOf(p) | |||
} | |||
return values, nil | |||
} | |||
// convert a list of values to a populated struct with the correct types | |||
func returnsToResponse(funcInfo *FuncWrapper, returns []reflect.Value) (interface{}, error) { | |||
returnTypes := funcInfo.returns | |||
finalType := returnTypes[len(returnTypes)-1] | |||
if finalType.Implements(reflect.TypeOf((*error)(nil)).Elem()) { | |||
errV := returns[len(returnTypes)-1] | |||
return nil, errV.Interface().(error) | |||
} | |||
v := funcInfo.response.Elem() | |||
nFields := v.NumField() | |||
for i := 0; i < nFields; i++ { | |||
field := v.FieldByIndex([]int{i}) | |||
field.Set(returns[i]) | |||
} | |||
return v.Interface(), nil | |||
} | |||
// jsonrpc calls grab the given method's function info and runs reflect.Call | |||
func JsonRpcHandler(w http.ResponseWriter, r *http.Request) { | |||
b, _ := ioutil.ReadAll(r.Body) | |||
var jrpc JsonRpc | |||
err := json.Unmarshal(b, &jrpc) | |||
if err != nil { | |||
// TODO | |||
} | |||
funcInfo := funcMap[jrpc.Method] | |||
values, err := paramsToValues(funcInfo, jrpc.Params) | |||
if err != nil { | |||
WriteAPIResponse(w, API_INVALID_PARAM, err.Error()) | |||
return | |||
} | |||
returns := funcInfo.f.Call(values) | |||
response, err := returnsToResponse(funcInfo, returns) | |||
if err != nil { | |||
WriteAPIResponse(w, API_ERROR, err.Error()) | |||
} | |||
WriteAPIResponse(w, API_OK, response) | |||
} | |||
func initHandlers() { | |||
http.HandleFunc("/status", StatusHandler) | |||
http.HandleFunc("/net_info", NetInfoHandler) | |||
http.HandleFunc("/blockchain", BlockchainInfoHandler) | |||
http.HandleFunc("/get_block", GetBlockHandler) | |||
http.HandleFunc("/get_account", GetAccountHandler) | |||
http.HandleFunc("/list_validators", ListValidatorsHandler) | |||
http.HandleFunc("/broadcast_tx", BroadcastTxHandler) | |||
// HTTP endpoints | |||
// toHandler runs once for each function and caches | |||
// all reflection data | |||
http.HandleFunc("/status", toHandler("status")) | |||
http.HandleFunc("/net_info", toHandler("net_info")) | |||
http.HandleFunc("/blockchain", toHandler("blockchain")) | |||
http.HandleFunc("/get_block", toHandler("get_block")) | |||
http.HandleFunc("/get_account", toHandler("get_account")) | |||
http.HandleFunc("/list_validators", toHandler("list_validators")) | |||
http.HandleFunc("/broadcast_tx", toHandler("broadcast_tx")) | |||
http.HandleFunc("/list_accounts", toHandler("list_accounts")) | |||
http.HandleFunc("/unsafe/gen_priv_account", toHandler("gen_priv_account")) | |||
http.HandleFunc("/unsafe/sign_tx", toHandler("sign_tx")) | |||
//http.HandleFunc("/call", CallHandler) | |||
//http.HandleFunc("/get_storage", GetStorageHandler) | |||
http.HandleFunc("/develop/gen_priv_account", GenPrivAccountHandler) | |||
http.HandleFunc("/develop/list_accounts", ListAccountsHandler) | |||
http.HandleFunc("/develop/sign_tx", SignTxHandler) | |||
// JsonRPC endpoints | |||
http.HandleFunc("/", JsonRpcHandler) | |||
// unsafe JsonRPC endpoints | |||
//http.HandleFunc("/unsafe", UnsafeJsonRpcHandler) | |||
} | |||
type JsonRpc struct { | |||
JsonRpc string `json:"jsonrpc"` | |||
Method string `json:"method"` | |||
Params []interface{} `json:"params"` | |||
Id int `json:"id"` | |||
} | |||
// this will panic if not passed a function | |||
func funcArgTypes(f interface{}) []reflect.Type { | |||
t := reflect.TypeOf(f) | |||
n := t.NumIn() | |||
types := make([]reflect.Type, n) | |||
for i := 0; i < n; i++ { | |||
types[i] = t.In(i) | |||
} | |||
return types | |||
} | |||
func funcReturnTypes(f interface{}) []reflect.Type { | |||
t := reflect.TypeOf(f) | |||
n := t.NumOut() | |||
types := make([]reflect.Type, n) | |||
for i := 0; i < n; i++ { | |||
types[i] = t.Out(i) | |||
} | |||
return types | |||
} |
@ -1,57 +0,0 @@ | |||
package rpc | |||
import ( | |||
"net/http" | |||
"github.com/tendermint/tendermint/binary" | |||
. "github.com/tendermint/tendermint/common" | |||
"github.com/tendermint/tendermint/merkle" | |||
"github.com/tendermint/tendermint/state" | |||
"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 | |||
var tx types.Tx | |||
binary.ReadJSON(&tx, []byte(txJSON), &err) | |||
if err != nil { | |||
WriteAPIResponse(w, API_INVALID_PARAM, Fmt("Invalid tx: %v", err)) | |||
return | |||
} | |||
err = mempoolReactor.BroadcastTx(tx) | |||
if err != nil { | |||
WriteAPIResponse(w, API_ERROR, Fmt("Error broadcasting transaction: %v", err)) | |||
return | |||
} | |||
txHash := merkle.HashFromBinary(tx) | |||
var createsContract bool | |||
var contractAddr []byte | |||
if callTx, ok := tx.(*types.CallTx); ok { | |||
if callTx.Address == nil { | |||
createsContract = true | |||
contractAddr = state.NewContractAddress(callTx.Input.Address, uint64(callTx.Input.Sequence)) | |||
} | |||
} | |||
WriteAPIResponse(w, API_OK, ResponseBroadcastTx{txHash, createsContract, contractAddr}) | |||
return | |||
} | |||
/* | |||
curl -H 'content-type: text/plain;' http://127.0.0.1:8888/submit_tx?tx=... | |||
*/ |
@ -1,55 +0,0 @@ | |||
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 := p2pSwitch.GetChainId() | |||
latestHeight := blockStore.Height() | |||
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) { | |||
o, i, _ := p2pSwitch.NumPeers() | |||
numPeers := o + i | |||
listening := p2pSwitch.IsListening() | |||
network := config.App().GetString("Network") | |||
WriteAPIResponse(w, API_OK, | |||
ResponseNetInfo{numPeers, listening, network}) | |||
} |
@ -0,0 +1,61 @@ | |||
package rpc | |||
import ( | |||
"github.com/tendermint/tendermint/account" | |||
sm "github.com/tendermint/tendermint/state" | |||
"github.com/tendermint/tendermint/types" | |||
) | |||
type ResponseGenPrivAccount struct { | |||
PrivAccount *account.PrivAccount | |||
} | |||
type ResponseGetAccount struct { | |||
Account *account.Account | |||
} | |||
type ResponseListAccounts struct { | |||
BlockHeight uint | |||
Accounts []*account.Account | |||
} | |||
type ResponseBlockchainInfo struct { | |||
LastHeight uint | |||
BlockMetas []*types.BlockMeta | |||
} | |||
type ResponseGetBlock struct { | |||
BlockMeta *types.BlockMeta | |||
Block *types.Block | |||
} | |||
// curl -H 'content-type: text/plain;' http://127.0.0.1:8888/submit_tx?tx=... | |||
type ResponseBroadcastTx struct { | |||
TxHash []byte | |||
CreatesContract bool | |||
ContractAddr []byte | |||
} | |||
type ResponseStatus struct { | |||
GenesisHash []byte | |||
Network string | |||
LatestBlockHash []byte | |||
LatestBlockHeight uint | |||
LatestBlockTime int64 // nano | |||
} | |||
type ResponseNetInfo struct { | |||
NumPeers int | |||
Listening bool | |||
Network string | |||
} | |||
type ResponseSignTx struct { | |||
Tx types.Tx | |||
} | |||
type ResponseListValidators struct { | |||
BlockHeight uint | |||
BondedValidators []*sm.Validator | |||
UnbondingValidators []*sm.Validator | |||
} |
@ -1,29 +0,0 @@ | |||
package rpc | |||
import ( | |||
"github.com/tendermint/tendermint/consensus" | |||
mempl "github.com/tendermint/tendermint/mempool" | |||
"github.com/tendermint/tendermint/p2p" | |||
"github.com/tendermint/tendermint/types" | |||
) | |||
var blockStore *types.BlockStore | |||
var consensusState *consensus.ConsensusState | |||
var mempoolReactor *mempl.MempoolReactor | |||
var p2pSwitch *p2p.Switch | |||
func SetRPCBlockStore(bs *types.BlockStore) { | |||
blockStore = bs | |||
} | |||
func SetRPCConsensusState(cs *consensus.ConsensusState) { | |||
consensusState = cs | |||
} | |||
func SetRPCMempoolReactor(mr *mempl.MempoolReactor) { | |||
mempoolReactor = mr | |||
} | |||
func SetRPCSwitch(sw *p2p.Switch) { | |||
p2pSwitch = sw | |||
} |
@ -0,0 +1,24 @@ | |||
{ | |||
"Accounts": [ | |||
{ | |||
"Address": "d7dff9806078899c8da3fe3633cc0bf3c6c2b1bb", | |||
"Amount": 200000000 | |||
}, | |||
{ | |||
"Address": "AC89A6DDF4C309A89A2C4078CE409A5A7B282270", | |||
"Amount": 200000000 | |||
} | |||
], | |||
"Validators": [ | |||
{ | |||
"PubKey": [1, "2239c21c81ea7173a6c489145490c015e05d4b97448933b708a7ec5b7b4921e3"], | |||
"Amount": 1000000, | |||
"UnbondTo": [ | |||
{ | |||
"Address": "d7dff9806078899c8da3fe3633cc0bf3c6c2b1bb", | |||
"Amount": 100000 | |||
} | |||
] | |||
} | |||
] | |||
} |
@ -0,0 +1 @@ | |||
{"Address":"D7DFF9806078899C8DA3FE3633CC0BF3C6C2B1BB","PubKey":[1,"2239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"],"PrivKey":[1,"FDE3BD94CB327D19464027BA668194C5EFA46AE83E8419D7542CFF41F00C81972239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"],"LastHeight":3,"LastRound":0,"LastStep":2} |
@ -1,66 +0,0 @@ | |||
package rpc | |||
import ( | |||
"net/http" | |||
"github.com/tendermint/tendermint/account" | |||
"github.com/tendermint/tendermint/binary" | |||
. "github.com/tendermint/tendermint/common" | |||
"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") | |||
var err error | |||
var tx types.Tx | |||
binary.ReadJSON(&tx, []byte(txStr), &err) | |||
if err != nil { | |||
WriteAPIResponse(w, API_INVALID_PARAM, Fmt("Invalid tx: %v", err)) | |||
return | |||
} | |||
privAccounts := binary.ReadJSON([]*account.PrivAccount{}, []byte(privAccountsStr), &err).([]*account.PrivAccount) | |||
if err != nil { | |||
WriteAPIResponse(w, API_INVALID_PARAM, Fmt("Invalid privAccounts: %v", err)) | |||
return | |||
} | |||
for i, privAccount := range privAccounts { | |||
if privAccount == nil || privAccount.PrivKey == nil { | |||
WriteAPIResponse(w, API_INVALID_PARAM, Fmt("Invalid (empty) privAccount @%v", i)) | |||
return | |||
} | |||
} | |||
switch tx.(type) { | |||
case *types.SendTx: | |||
sendTx := tx.(*types.SendTx) | |||
for i, input := range sendTx.Inputs { | |||
input.PubKey = privAccounts[i].PubKey | |||
input.Signature = privAccounts[i].Sign(sendTx) | |||
} | |||
case *types.BondTx: | |||
bondTx := tx.(*types.BondTx) | |||
for i, input := range bondTx.Inputs { | |||
input.PubKey = privAccounts[i].PubKey | |||
input.Signature = privAccounts[i].Sign(bondTx) | |||
} | |||
case *types.UnbondTx: | |||
unbondTx := tx.(*types.UnbondTx) | |||
unbondTx.Signature = privAccounts[0].Sign(unbondTx).(account.SignatureEd25519) | |||
case *types.RebondTx: | |||
rebondTx := tx.(*types.RebondTx) | |||
rebondTx.Signature = privAccounts[0].Sign(rebondTx).(account.SignatureEd25519) | |||
} | |||
WriteAPIResponse(w, API_OK, ResponseSignTx{tx}) | |||
} |
@ -1,36 +0,0 @@ | |||
package rpc | |||
import ( | |||
"net/http" | |||
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 | |||
var unbondingValidators []*sm.Validator | |||
state := consensusState.GetState() | |||
blockHeight = state.LastBlockHeight | |||
state.BondedValidators.Iterate(func(index uint, val *sm.Validator) bool { | |||
bondedValidators = append(bondedValidators, val) | |||
return false | |||
}) | |||
state.UnbondingValidators.Iterate(func(index uint, val *sm.Validator) bool { | |||
unbondingValidators = append(unbondingValidators, val) | |||
return false | |||
}) | |||
WriteAPIResponse(w, API_OK, ResponseListValidators{blockHeight, bondedValidators, unbondingValidators}) | |||
} |