tendermint/cmd/debora/commands.go

83 lines
2.9 KiB
Go

package main
import (
"fmt"
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"
)
// These are convenience functions for a single developer.
// When multiple are involved, the workflow is different.
// (First the command(s) are signed by all validators,
// and then it is broadcast).
func RunProcess(privKey acm.PrivKey, remote string, command btypes.CommandRunProcess) (response btypes.ResponseRunProcess, err error) {
nonce, err := GetNonce(remote)
if err != nil {
return response, err
}
commandBytes, signature := SignCommand(privKey, nonce+1, command)
_, err = RunAuthCommand(remote, commandBytes, []acm.Signature{signature}, &response)
return response, err
}
func StopProcess(privKey acm.PrivKey, remote string, command btypes.CommandStopProcess) (response btypes.ResponseStopProcess, err error) {
nonce, err := GetNonce(remote)
if err != nil {
return response, err
}
commandBytes, signature := SignCommand(privKey, nonce+1, command)
_, err = RunAuthCommand(remote, commandBytes, []acm.Signature{signature}, &response)
return response, err
}
func ListProcesses(privKey acm.PrivKey, remote string, command btypes.CommandListProcesses) (response btypes.ResponseListProcesses, err error) {
nonce, err := GetNonce(remote)
if err != nil {
return response, err
}
commandBytes, signature := SignCommand(privKey, nonce+1, command)
_, 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, error) {
response, err := GetStatus(remote)
return response.Nonce, err
}
func GetStatus(remote string) (response btypes.ResponseStatus, err error) {
_, err = rpc.Call(remote, "status", Arr(), &response)
if err != nil {
return response, fmt.Errorf("Error fetching nonce from remote %v:\n %v", remote, err)
}
return response, nil
}
// 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)
}