diff --git a/node/node.go b/node/node.go index e47de0fdf..d9b548091 100644 --- a/node/node.go +++ b/node/node.go @@ -175,6 +175,8 @@ func (n *Node) AddListener(l p2p.Listener) { } func (n *Node) StartRPC() ([]net.Listener, error) { + rpccore.SetConfig(n.config) + rpccore.SetBlockStore(n.blockStore) rpccore.SetConsensusState(n.consensusState) rpccore.SetConsensusReactor(n.consensusReactor) diff --git a/rpc/core/dev.go b/rpc/core/dev.go index 63cca800c..2b8dfb8f3 100644 --- a/rpc/core/dev.go +++ b/rpc/core/dev.go @@ -1,12 +1,39 @@ package core import ( + "fmt" "os" "runtime/pprof" + "strconv" ctypes "github.com/tendermint/tendermint/rpc/core/types" ) +func UnsafeSetConfig(typ, key, value string) (*ctypes.ResultUnsafeSetConfig, error) { + switch typ { + case "string": + config.Set(key, value) + case "int": + val, err := strconv.Atoi(value) + if err != nil { + return nil, fmt.Errorf("non-integer value found. key:%s; value:%s; err:%v", key, value, err) + } + config.Set(key, val) + case "bool": + switch value { + case "true": + config.Set(key, true) + case "false": + config.Set(key, false) + default: + return nil, fmt.Errorf("bool value must be true or false. got %s", value) + } + default: + return nil, fmt.Errorf("Unknown type %s", typ) + } + return &ctypes.ResultUnsafeSetConfig{}, nil +} + var profFile *os.File func UnsafeStartCPUProfiler(filename string) (*ctypes.ResultUnsafeProfile, error) { diff --git a/rpc/core/pipe.go b/rpc/core/pipe.go index ae00d7b47..de196e813 100644 --- a/rpc/core/pipe.go +++ b/rpc/core/pipe.go @@ -1,7 +1,9 @@ package core import ( + cfg "github.com/tendermint/go-config" "github.com/tendermint/go-p2p" + bc "github.com/tendermint/tendermint/blockchain" "github.com/tendermint/tendermint/consensus" mempl "github.com/tendermint/tendermint/mempool" @@ -16,6 +18,12 @@ var p2pSwitch *p2p.Switch var privValidator *types.PrivValidator var genDoc *types.GenesisDoc // cache the genesis structure +var config cfg.Config = nil + +func SetConfig(c cfg.Config) { + config = c +} + func SetBlockStore(bs *bc.BlockStore) { blockStore = bs } diff --git a/rpc/core/routes.go b/rpc/core/routes.go index 30861b0f9..585a18cd2 100644 --- a/rpc/core/routes.go +++ b/rpc/core/routes.go @@ -24,6 +24,7 @@ var Routes = map[string]*rpc.RPCFunc{ "unconfirmed_txs": rpc.NewRPCFunc(UnconfirmedTxsResult, ""), "num_unconfirmed_txs": rpc.NewRPCFunc(NumUnconfirmedTxsResult, ""), + "unsafe_set_config": rpc.NewRPCFunc(UnsafeSetConfigResult, "type,key,value"), "unsafe_start_cpu_profiler": rpc.NewRPCFunc(UnsafeStartCPUProfilerResult, "filename"), "unsafe_stop_cpu_profiler": rpc.NewRPCFunc(UnsafeStopCPUProfilerResult, ""), "unsafe_write_heap_profile": rpc.NewRPCFunc(UnsafeWriteHeapProfileResult, "filename"), @@ -141,6 +142,14 @@ func BroadcastTxAsyncResult(tx []byte) (ctypes.TMResult, error) { } } +func UnsafeSetConfigResult(typ, key, value string) (ctypes.TMResult, error) { + if r, err := UnsafeSetConfig(typ, key, value); err != nil { + return nil, err + } else { + return r, nil + } +} + func UnsafeStartCPUProfilerResult(filename string) (ctypes.TMResult, error) { if r, err := UnsafeStartCPUProfiler(filename); err != nil { return nil, err diff --git a/rpc/test/client_test.go b/rpc/test/client_test.go index 6508a8461..a5b243bea 100644 --- a/rpc/test/client_test.go +++ b/rpc/test/client_test.go @@ -155,3 +155,60 @@ func TestWSDoubleFire(t *testing.T) { return nil }) }*/ + +//-------------------------------------------------------------------------------- +// unsafe_set_config + +var stringVal = "my string" +var intVal = 987654321 +var boolVal = true + +// don't change these +var testCasesUnsafeSetConfig = [][]string{ + []string{"string", "key1", stringVal}, + []string{"int", "key2", fmt.Sprintf("%v", intVal)}, + []string{"bool", "key3", fmt.Sprintf("%v", boolVal)}, +} + +func TestURIUnsafeSetConfig(t *testing.T) { + for _, testCase := range testCasesUnsafeSetConfig { + tmResult := new(ctypes.TMResult) + _, err := clientURI.Call("unsafe_set_config", map[string]interface{}{ + "type": testCase[0], + "key": testCase[1], + "value": testCase[2], + }, tmResult) + if err != nil { + t.Fatal(err) + } + } + testUnsafeSetConfig(t) +} + +func TestJSONUnsafeSetConfig(t *testing.T) { + for _, testCase := range testCasesUnsafeSetConfig { + tmResult := new(ctypes.TMResult) + _, err := clientJSON.Call("unsafe_set_config", []interface{}{testCase[0], testCase[1], testCase[2]}, tmResult) + if err != nil { + t.Fatal(err) + } + } + testUnsafeSetConfig(t) +} + +func testUnsafeSetConfig(t *testing.T) { + s := config.GetString("key1") + if s != stringVal { + t.Fatalf("got %v, expected %v", s, stringVal) + } + + i := config.GetInt("key2") + if i != intVal { + t.Fatalf("got %v, expected %v", i, intVal) + } + + b := config.GetBool("key3") + if b != boolVal { + t.Fatalf("got %v, expected %v", b, boolVal) + } +}