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.

82 lines
2.9 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. response, err := GetStatus(remote)
  46. return response.Nonce, err
  47. }
  48. func GetStatus(remote string) (response btypes.ResponseStatus, err error) {
  49. _, err = rpc.Call(remote, "status", Arr(), &response)
  50. if err != nil {
  51. return response, fmt.Errorf("Error fetching nonce from remote %v:\n %v", remote, err)
  52. }
  53. return response, nil
  54. }
  55. // Each developer runs this
  56. func SignCommand(privKey acm.PrivKey, nonce uint64, command btypes.Command) ([]byte, acm.Signature) {
  57. noncedCommand := btypes.NoncedCommand{
  58. Nonce: nonce,
  59. Command: command,
  60. }
  61. commandJSONBytes := binary.JSONBytes(noncedCommand)
  62. signature := privKey.Sign(commandJSONBytes)
  63. return commandJSONBytes, signature
  64. }
  65. // Somebody aggregates the signatures and calls this.
  66. func RunAuthCommand(remote string, commandJSONBytes []byte, signatures []acm.Signature, dest interface{}) (interface{}, error) {
  67. authCommand := btypes.AuthCommand{
  68. CommandJSONStr: string(commandJSONBytes),
  69. Signatures: signatures,
  70. }
  71. return rpc.Call(remote, "run", Arr(authCommand), dest)
  72. }