mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-15 06:11:20 +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"}),
|
||||
"list_unconfirmed_txs": rpc.NewRPCFunc(ListUnconfirmedTxs, []string{}),
|
||||
"list_accounts": rpc.NewRPCFunc(ListAccounts, []string{}),
|
||||
"name_reg_entry": rpc.NewRPCFunc(NameRegEntry, []string{"name"}),
|
||||
"unsafe/gen_priv_account": rpc.NewRPCFunc(GenPrivAccount, []string{}),
|
||||
"unsafe/sign_tx": rpc.NewRPCFunc(SignTx, []string{"tx", "privAccounts"}),
|
||||
}
|
||||
|
@ -100,3 +100,7 @@ type ResponseDumpConsensusState struct {
|
||||
RoundState string `json:"round_state"`
|
||||
PeerRoundStates []string `json:"peer_round_states"`
|
||||
}
|
||||
|
||||
type ResponseNameRegEntry struct {
|
||||
Entry *types.NameRegEntry `json:"entry"`
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/tendermint/tendermint/binary"
|
||||
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"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -30,6 +28,7 @@ var reverseFuncMap = map[string]string{
|
||||
"DumpStorage": "dump_storage",
|
||||
"BroadcastTx": "broadcast_tx",
|
||||
"ListAccounts": "list_accounts",
|
||||
"NameRegEntry": "name_reg_entry",
|
||||
"GenPrivAccount": "unsafe/gen_priv_account",
|
||||
"SignTx": "unsafe/sign_tx",
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ type Client interface {
|
||||
ListAccounts() (*ctypes.ResponseListAccounts, error)
|
||||
ListUnconfirmedTxs() (*ctypes.ResponseListUnconfirmedTxs, error)
|
||||
ListValidators() (*ctypes.ResponseListValidators, error)
|
||||
NameRegEntry(name []byte) (*ctypes.ResponseNameRegEntry, error)
|
||||
NetInfo() (*ctypes.ResponseNetInfo, error)
|
||||
SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (*ctypes.ResponseSignTx, error)
|
||||
Status() (*ctypes.ResponseStatus, error)
|
||||
@ -453,6 +454,36 @@ func (c *ClientHTTP) ListValidators() (*ctypes.ResponseListValidators, error) {
|
||||
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) {
|
||||
values, err := argsToURLValues(nil)
|
||||
if err != nil {
|
||||
@ -921,6 +952,33 @@ func (c *ClientJSON) ListValidators() (*ctypes.ResponseListValidators, error) {
|
||||
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) {
|
||||
request := rpctypes.RPCRequest{
|
||||
JSONRPC: "2.0",
|
||||
|
@ -40,6 +40,10 @@ func TestHTTPCallContract(t *testing.T) {
|
||||
testCall(t, "HTTP")
|
||||
}
|
||||
|
||||
func TestHTTPNameReg(t *testing.T) {
|
||||
testNameReg(t, "HTTP")
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Test the JSONRPC client
|
||||
|
||||
@ -74,3 +78,7 @@ func TestJSONCallCode(t *testing.T) {
|
||||
func TestJSONCallContract(t *testing.T) {
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@ -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
|
||||
|
||||
|
@ -190,3 +190,33 @@ func testCall(t *testing.T, typ string) {
|
||||
expected := []byte{0xb}
|
||||
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)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
|
||||
|
Reference in New Issue
Block a user