diff --git a/cmd/barak/main.go b/cmd/barak/main.go index bfdb66d63..c5b4d672a 100644 --- a/cmd/barak/main.go +++ b/cmd/barak/main.go @@ -22,7 +22,8 @@ import ( ) var Routes = map[string]*rpc.RPCFunc{ - "run": rpc.NewRPCFunc(Run, []string{"auth_command"}), + "status": rpc.NewRPCFunc(Status, []string{}), + "run": rpc.NewRPCFunc(Run, []string{"auth_command"}), // NOTE: also, two special non-JSONRPC routes called "download" and "upload" } @@ -72,7 +73,19 @@ func main() { } //------------------------------------------------------------------------------ -// RPC main function +// RPC functions + +func Status() (*ResponseStatus, error) { + barak.mtx.Lock() + nonce := barak.nonce + validators := barak.validators + barak.mtx.Unlock() + + return &ResponseStatus{ + Nonce: nonce, + Validators: validators, + }, nil +} func Run(authCommand AuthCommand) (interface{}, error) { command, err := parseValidateCommand(authCommand) diff --git a/cmd/barak/types/responses.go b/cmd/barak/types/responses.go index 74b4b28cd..3f076ed52 100644 --- a/cmd/barak/types/responses.go +++ b/cmd/barak/types/responses.go @@ -4,6 +4,11 @@ import ( pcm "github.com/tendermint/tendermint/process" ) +type ResponseStatus struct { + Nonce uint64 + Validators []Validator +} + type ResponseRunProcess struct { } diff --git a/cmd/barak/types/validator.go b/cmd/barak/types/validator.go new file mode 100644 index 000000000..252f3dc59 --- /dev/null +++ b/cmd/barak/types/validator.go @@ -0,0 +1,10 @@ +package types + +import ( + acm "github.com/tendermint/tendermint/account" +) + +type Validator struct { + VotingPower uint64 + PubKey acm.PubKey +} diff --git a/cmd/barak/validate.go b/cmd/barak/validate.go index c8935c376..df7b420bf 100644 --- a/cmd/barak/validate.go +++ b/cmd/barak/validate.go @@ -1,11 +1,9 @@ package main -import acm "github.com/tendermint/tendermint/account" - -type Validator struct { - VotingPower uint64 - PubKey acm.PubKey -} +import ( + acm "github.com/tendermint/tendermint/account" + . "github.com/tendermint/tendermint/cmd/barak/types" +) func validate(signBytes []byte, validators []Validator, signatures []acm.Signature) bool { var signedPower uint64 diff --git a/cmd/debora/commands.go b/cmd/debora/commands.go new file mode 100644 index 000000000..37a9b41a8 --- /dev/null +++ b/cmd/debora/commands.go @@ -0,0 +1,53 @@ +package main + +import ( + acm "github.com/tendermint/tendermint/account" + "github.com/tendermint/tendermint/binary" + btypes "github.com/tendermint/tendermint/cmd/barak/types" + . "github.com/tendermint/tendermint/common" + "github.com/tendermint/tendermint/rpc" +) + +// Convenience function for a single validator. +func ListProcesses(privKey acm.PrivKey, remote string) (btypes.ResponseListProcesses, error) { + command := btypes.CommandListProcesses{} + nonce := GetNonce(remote) + commandBytes, signature := SignCommand(privKey, nonce+1, command) + response := btypes.ResponseListProcesses{} + _, err := RunAuthCommand(remote, commandBytes, []acm.Signature{signature}, &response) + return response, err +} + +//----------------------------------------------------------------------------- + +// Utility method to get nonce from the remote. +// The next command should include the returned nonce+1 as nonce. +func GetNonce(remote string) uint64 { + var err error + response := btypes.ResponseStatus{} + _, err = rpc.Call(remote, "status", Arr(), &response) + if err != nil { + panic(Fmt("Error fetching nonce from remote %v: %v", remote, err)) + } + return response.Nonce +} + +// Each developer runs this +func SignCommand(privKey acm.PrivKey, nonce uint64, command btypes.Command) ([]byte, acm.Signature) { + noncedCommand := btypes.NoncedCommand{ + Nonce: nonce, + Command: command, + } + commandJSONBytes := binary.JSONBytes(noncedCommand) + signature := privKey.Sign(commandJSONBytes) + return commandJSONBytes, signature +} + +// Somebody aggregates the signatures and calls this. +func RunAuthCommand(remote string, commandJSONBytes []byte, signatures []acm.Signature, dest interface{}) (interface{}, error) { + authCommand := btypes.AuthCommand{ + CommandJSONStr: string(commandJSONBytes), + Signatures: signatures, + } + return rpc.Call(remote, "run", Arr(authCommand), dest) +} diff --git a/cmd/debora/main.go b/cmd/debora/main.go index bc436b862..5f5bacf8f 100644 --- a/cmd/debora/main.go +++ b/cmd/debora/main.go @@ -2,19 +2,18 @@ package main import ( "fmt" - btypes "github.com/tendermint/tendermint/cmd/barak/types" - . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/rpc" - // ctypes "github.com/tendermint/tendermint/rpc/core/types" + + acm "github.com/tendermint/tendermint/account" + "github.com/tendermint/tendermint/binary" ) func main() { - // XXX Need to get PrivAccount somehow to sign the request. - // XXX Actually, more like, how do I even sign these? - // XXX Let's just sign it janky for now and modify later. - - response := []btypes.ResponseListProcesses{} - response2, err := rpc.Call("http://127.0.0.1:8082", "list_processes", Arr(), &response) - fmt.Printf("%v\n", response) - fmt.Printf("%v (error: %v)\n", response2, err) + var remote string = "http://127.0.0.1:8082" + var err error + var privKey acm.PrivKey + binary.ReadJSON(&privKey, []byte(` + [1,"PRIVKEYBYTES"] + `), &err) + response, err := ListProcesses(privKey, remote) + fmt.Printf("%v (error: %v)\n", response, err) } diff --git a/rpc/handlers.go b/rpc/handlers.go index 9bc24c889..51dd7e5e2 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -3,6 +3,7 @@ package rpc import ( "bytes" "encoding/json" + "errors" "fmt" "github.com/tendermint/tendermint/binary" "github.com/tendermint/tendermint/events" @@ -113,6 +114,10 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc { // covert a list of interfaces to properly typed values func jsonParamsToArgs(rpcFunc *RPCFunc, params []interface{}) ([]reflect.Value, error) { + if len(rpcFunc.argNames) != len(params) { + return nil, errors.New(fmt.Sprintf("Expected %v parameters (%v), got %v (%v)", + len(rpcFunc.argNames), rpcFunc.argNames, len(params), params)) + } values := make([]reflect.Value, len(params)) for i, p := range params { ty := rpcFunc.args[i]