mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-17 15:11:21 +00:00
namereg rpc and tests
This commit is contained in:
17
rpc/core/names.go
Normal file
17
rpc/core/names.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// XXX: need we be careful about rendering bytes as string or is that their problem ?
|
||||||
|
func NameRegEntry(name []byte) (*ctypes.ResponseNameRegEntry, error) {
|
||||||
|
st := consensusState.GetState() // performs a copy
|
||||||
|
entry := st.GetNameRegEntry(name)
|
||||||
|
if entry == nil {
|
||||||
|
return nil, fmt.Errorf("Name %s not found", name)
|
||||||
|
}
|
||||||
|
return &ctypes.ResponseNameRegEntry{entry}, nil
|
||||||
|
}
|
@ -20,6 +20,7 @@ var Routes = map[string]*rpc.RPCFunc{
|
|||||||
"broadcast_tx": rpc.NewRPCFunc(BroadcastTx, []string{"tx"}),
|
"broadcast_tx": rpc.NewRPCFunc(BroadcastTx, []string{"tx"}),
|
||||||
"list_unconfirmed_txs": rpc.NewRPCFunc(ListUnconfirmedTxs, []string{}),
|
"list_unconfirmed_txs": rpc.NewRPCFunc(ListUnconfirmedTxs, []string{}),
|
||||||
"list_accounts": rpc.NewRPCFunc(ListAccounts, []string{}),
|
"list_accounts": rpc.NewRPCFunc(ListAccounts, []string{}),
|
||||||
|
"name_reg_entry": rpc.NewRPCFunc(NameRegEntry, []string{"name"}),
|
||||||
"unsafe/gen_priv_account": rpc.NewRPCFunc(GenPrivAccount, []string{}),
|
"unsafe/gen_priv_account": rpc.NewRPCFunc(GenPrivAccount, []string{}),
|
||||||
"unsafe/sign_tx": rpc.NewRPCFunc(SignTx, []string{"tx", "privAccounts"}),
|
"unsafe/sign_tx": rpc.NewRPCFunc(SignTx, []string{"tx", "privAccounts"}),
|
||||||
}
|
}
|
||||||
|
@ -100,3 +100,7 @@ type ResponseDumpConsensusState struct {
|
|||||||
RoundState string `json:"round_state"`
|
RoundState string `json:"round_state"`
|
||||||
PeerRoundStates []string `json:"peer_round_states"`
|
PeerRoundStates []string `json:"peer_round_states"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResponseNameRegEntry struct {
|
||||||
|
Entry *types.NameRegEntry `json:"entry"`
|
||||||
|
}
|
||||||
|
@ -5,8 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/tendermint/tendermint/binary"
|
"github.com/tendermint/tendermint/binary"
|
||||||
rpctypes "github.com/tendermint/tendermint/rpc/types"
|
rpctypes "github.com/tendermint/tendermint/rpc/types"
|
||||||
// NOTE: do not import rpc/core.
|
|
||||||
// What kind of client imports all of core logic? :P
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -30,6 +28,7 @@ var reverseFuncMap = map[string]string{
|
|||||||
"DumpStorage": "dump_storage",
|
"DumpStorage": "dump_storage",
|
||||||
"BroadcastTx": "broadcast_tx",
|
"BroadcastTx": "broadcast_tx",
|
||||||
"ListAccounts": "list_accounts",
|
"ListAccounts": "list_accounts",
|
||||||
|
"NameRegEntry": "name_reg_entry",
|
||||||
"GenPrivAccount": "unsafe/gen_priv_account",
|
"GenPrivAccount": "unsafe/gen_priv_account",
|
||||||
"SignTx": "unsafe/sign_tx",
|
"SignTx": "unsafe/sign_tx",
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ type Client interface {
|
|||||||
ListAccounts() (*ctypes.ResponseListAccounts, error)
|
ListAccounts() (*ctypes.ResponseListAccounts, error)
|
||||||
ListUnconfirmedTxs() (*ctypes.ResponseListUnconfirmedTxs, error)
|
ListUnconfirmedTxs() (*ctypes.ResponseListUnconfirmedTxs, error)
|
||||||
ListValidators() (*ctypes.ResponseListValidators, error)
|
ListValidators() (*ctypes.ResponseListValidators, error)
|
||||||
|
NameRegEntry(name []byte) (*ctypes.ResponseNameRegEntry, error)
|
||||||
NetInfo() (*ctypes.ResponseNetInfo, error)
|
NetInfo() (*ctypes.ResponseNetInfo, error)
|
||||||
SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (*ctypes.ResponseSignTx, error)
|
SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (*ctypes.ResponseSignTx, error)
|
||||||
Status() (*ctypes.ResponseStatus, error)
|
Status() (*ctypes.ResponseStatus, error)
|
||||||
@ -453,6 +454,36 @@ func (c *ClientHTTP) ListValidators() (*ctypes.ResponseListValidators, error) {
|
|||||||
return response.Result, nil
|
return response.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ClientHTTP) NameRegEntry(name []byte) (*ctypes.ResponseNameRegEntry, error) {
|
||||||
|
values, err := argsToURLValues([]string{"name"}, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := http.PostForm(c.addr+reverseFuncMap["NameRegEntry"], values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var response struct {
|
||||||
|
Result *ctypes.ResponseNameRegEntry `json:"result"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
JSONRPC string `json:"jsonrpc"`
|
||||||
|
}
|
||||||
|
binary.ReadJSON(&response, body, &err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
return response.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ClientHTTP) NetInfo() (*ctypes.ResponseNetInfo, error) {
|
func (c *ClientHTTP) NetInfo() (*ctypes.ResponseNetInfo, error) {
|
||||||
values, err := argsToURLValues(nil)
|
values, err := argsToURLValues(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -921,6 +952,33 @@ func (c *ClientJSON) ListValidators() (*ctypes.ResponseListValidators, error) {
|
|||||||
return response.Result, nil
|
return response.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ClientJSON) NameRegEntry(name []byte) (*ctypes.ResponseNameRegEntry, error) {
|
||||||
|
request := rpctypes.RPCRequest{
|
||||||
|
JSONRPC: "2.0",
|
||||||
|
Method: reverseFuncMap["NameRegEntry"],
|
||||||
|
Params: []interface{}{name},
|
||||||
|
Id: 0,
|
||||||
|
}
|
||||||
|
body, err := c.RequestResponse(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var response struct {
|
||||||
|
Result *ctypes.ResponseNameRegEntry `json:"result"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
JSONRPC string `json:"jsonrpc"`
|
||||||
|
}
|
||||||
|
binary.ReadJSON(&response, body, &err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
return response.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ClientJSON) NetInfo() (*ctypes.ResponseNetInfo, error) {
|
func (c *ClientJSON) NetInfo() (*ctypes.ResponseNetInfo, error) {
|
||||||
request := rpctypes.RPCRequest{
|
request := rpctypes.RPCRequest{
|
||||||
JSONRPC: "2.0",
|
JSONRPC: "2.0",
|
||||||
|
@ -40,6 +40,10 @@ func TestHTTPCallContract(t *testing.T) {
|
|||||||
testCall(t, "HTTP")
|
testCall(t, "HTTP")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHTTPNameReg(t *testing.T) {
|
||||||
|
testNameReg(t, "HTTP")
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// Test the JSONRPC client
|
// Test the JSONRPC client
|
||||||
|
|
||||||
@ -74,3 +78,7 @@ func TestJSONCallCode(t *testing.T) {
|
|||||||
func TestJSONCallContract(t *testing.T) {
|
func TestJSONCallContract(t *testing.T) {
|
||||||
testCall(t, "JSONRPC")
|
testCall(t, "JSONRPC")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJSONNameReg(t *testing.T) {
|
||||||
|
testNameReg(t, "JSONRPC")
|
||||||
|
}
|
||||||
|
@ -120,6 +120,13 @@ func makeDefaultCallTx(t *testing.T, typ string, addr, code []byte, amt, gasLim,
|
|||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeDefaultNameTx(t *testing.T, typ string, name, value []byte, amt, fee uint64) *types.NameTx {
|
||||||
|
nonce := getNonce(t, typ, user[0].Address)
|
||||||
|
tx := types.NewNameTxWithNonce(user[0].PubKey, name, value, amt, fee, nonce)
|
||||||
|
tx.Sign(user[0])
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
// rpc call wrappers (fail on err)
|
// rpc call wrappers (fail on err)
|
||||||
|
|
||||||
@ -210,6 +217,16 @@ func callContract(t *testing.T, client cclient.Client, address, data, expected [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the namereg entry
|
||||||
|
func getNameRegEntry(t *testing.T, typ string, name []byte) *types.NameRegEntry {
|
||||||
|
client := clients[typ]
|
||||||
|
r, err := client.NameRegEntry(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return r.Entry
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// utility verification function
|
// utility verification function
|
||||||
|
|
||||||
|
@ -190,3 +190,33 @@ func testCall(t *testing.T, typ string) {
|
|||||||
expected := []byte{0xb}
|
expected := []byte{0xb}
|
||||||
callContract(t, client, contractAddr, data, expected)
|
callContract(t, client, contractAddr, data, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testNameReg(t *testing.T, typ string) {
|
||||||
|
con := newWSCon(t)
|
||||||
|
eid := types.EventStringNewBlock()
|
||||||
|
subscribe(t, con, eid)
|
||||||
|
defer func() {
|
||||||
|
unsubscribe(t, con, eid)
|
||||||
|
con.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
amt, fee := uint64(6969), uint64(1000)
|
||||||
|
// since entries ought to be unique and these run against different clients, we append the typ
|
||||||
|
name := []byte("ye-old-domain-name-" + typ)
|
||||||
|
data := []byte("these are amongst the things I wish to bestow upon the youth of generations come: a safe supply of honey, and a better money. For what else shall they need?")
|
||||||
|
tx := makeDefaultNameTx(t, typ, name, data, amt, fee)
|
||||||
|
broadcastTx(t, typ, tx)
|
||||||
|
|
||||||
|
// allow it to get mined
|
||||||
|
waitForEvent(t, con, eid, true, func() {
|
||||||
|
}, func(eid string, b []byte) error {
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
entry := getNameRegEntry(t, typ, name)
|
||||||
|
|
||||||
|
if bytes.Compare(entry.Data, data) != 0 {
|
||||||
|
t.Fatal(fmt.Sprintf("Got %s, expected %s", entry.Data, data))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -103,6 +103,43 @@ func (tx *CallTx) Sign(chainID string, privAccount *account.PrivAccount) {
|
|||||||
tx.Input.Signature = privAccount.Sign(chainID, tx)
|
tx.Input.Signature = privAccount.Sign(chainID, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// NameTx interface for creating tx
|
||||||
|
|
||||||
|
func NewNameTx(st AccountGetter, from account.PubKey, name, data []byte, amt, fee uint64) (*NameTx, error) {
|
||||||
|
addr := from.Address()
|
||||||
|
acc := st.GetAccount(addr)
|
||||||
|
if acc == nil {
|
||||||
|
return nil, fmt.Errorf("Invalid address %X from pubkey %X", addr, from)
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce := uint64(acc.Sequence)
|
||||||
|
return NewNameTxWithNonce(from, name, data, amt, fee, nonce), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNameTxWithNonce(from account.PubKey, name, data []byte, amt, fee, nonce uint64) *NameTx {
|
||||||
|
addr := from.Address()
|
||||||
|
input := &TxInput{
|
||||||
|
Address: addr,
|
||||||
|
Amount: amt,
|
||||||
|
Sequence: uint(nonce) + 1,
|
||||||
|
Signature: account.SignatureEd25519{},
|
||||||
|
PubKey: from,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &NameTx{
|
||||||
|
Input: input,
|
||||||
|
Name: name,
|
||||||
|
Data: data,
|
||||||
|
Fee: fee,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *NameTx) Sign(privAccount *account.PrivAccount) {
|
||||||
|
tx.Input.PubKey = privAccount.PubKey
|
||||||
|
tx.Input.Signature = privAccount.Sign(tx)
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// BondTx interface for adding inputs/outputs and adding signatures
|
// BondTx interface for adding inputs/outputs and adding signatures
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user