You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
2.8 KiB

10 years ago
  1. package main
  2. import (
  3. "fmt"
  4. acm "github.com/tendermint/tendermint/account"
  5. "github.com/tendermint/tendermint/binary"
  6. btypes "github.com/tendermint/tendermint/cmd/barak/types"
  7. . "github.com/tendermint/tendermint/common"
  8. "github.com/tendermint/tendermint/rpc"
  9. )
  10. // These are convenience functions for a single developer.
  11. // When multiple are involved, the workflow is different.
  12. // (First the command(s) are signed by all validators,
  13. // and then it is broadcast).
  14. func RunProcess(privKey acm.PrivKey, remote string, command btypes.CommandRunProcess) (response btypes.ResponseRunProcess, err error) {
  15. nonce, err := GetNonce(remote)
  16. if err != nil {
  17. return response, err
  18. }
  19. commandBytes, signature := SignCommand(privKey, nonce+1, command)
  20. _, err = RunAuthCommand(remote, commandBytes, []acm.Signature{signature}, &response)
  21. return response, err
  22. }
  23. func StopProcess(privKey acm.PrivKey, remote string, command btypes.CommandStopProcess) (response btypes.ResponseStopProcess, err error) {
  24. nonce, err := GetNonce(remote)
  25. if err != nil {
  26. return response, err
  27. }
  28. commandBytes, signature := SignCommand(privKey, nonce+1, command)
  29. _, err = RunAuthCommand(remote, commandBytes, []acm.Signature{signature}, &response)
  30. return response, err
  31. }
  32. func ListProcesses(privKey acm.PrivKey, remote string, command btypes.CommandListProcesses) (response btypes.ResponseListProcesses, err error) {
  33. nonce, err := GetNonce(remote)
  34. if err != nil {
  35. return response, err
  36. }
  37. commandBytes, signature := SignCommand(privKey, nonce+1, command)
  38. _, err = RunAuthCommand(remote, commandBytes, []acm.Signature{signature}, &response)
  39. return response, err
  40. }
  41. //-----------------------------------------------------------------------------
  42. // Utility method to get nonce from the remote.
  43. // The next command should include the returned nonce+1 as nonce.
  44. func GetNonce(remote string) (uint64, error) {
  45. var err error
  46. response := btypes.ResponseStatus{}
  47. _, err = rpc.Call(remote, "status", Arr(), &response)
  48. if err != nil {
  49. return 0, fmt.Errorf("Error fetching nonce from remote %v:\n %v", remote, err)
  50. }
  51. return response.Nonce, nil
  52. }
  53. // Each developer runs this
  54. func SignCommand(privKey acm.PrivKey, nonce uint64, command btypes.Command) ([]byte, acm.Signature) {
  55. noncedCommand := btypes.NoncedCommand{
  56. Nonce: nonce,
  57. Command: command,
  58. }
  59. commandJSONBytes := binary.JSONBytes(noncedCommand)
  60. signature := privKey.Sign(commandJSONBytes)
  61. return commandJSONBytes, signature
  62. }
  63. // Somebody aggregates the signatures and calls this.
  64. func RunAuthCommand(remote string, commandJSONBytes []byte, signatures []acm.Signature, dest interface{}) (interface{}, error) {
  65. authCommand := btypes.AuthCommand{
  66. CommandJSONStr: string(commandJSONBytes),
  67. Signatures: signatures,
  68. }
  69. return rpc.Call(remote, "run", Arr(authCommand), dest)
  70. }