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.

57 lines
1.5 KiB

  1. package tx
  2. import (
  3. "github.com/pkg/errors"
  4. crypto "github.com/tendermint/go-crypto"
  5. data "github.com/tendermint/go-wire/data"
  6. )
  7. // OneSig lets us wrap arbitrary data with a go-crypto signature
  8. //
  9. // TODO: rethink how we want to integrate this with KeyStore so it makes
  10. // more sense (particularly the verify method)
  11. type OneSig struct {
  12. Data data.Bytes
  13. Signed
  14. }
  15. var _ SigInner = &OneSig{}
  16. func New(data []byte) Sig {
  17. return WrapSig(&OneSig{Data: data})
  18. }
  19. // SignBytes returns the original data passed into `NewSig`
  20. func (s *OneSig) SignBytes() []byte {
  21. return s.Data
  22. }
  23. // Sign will add a signature and pubkey.
  24. //
  25. // Depending on the Signable, one may be able to call this multiple times for multisig
  26. // Returns error if called with invalid data or too many times
  27. func (s *OneSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error {
  28. if pubkey.Empty() || sig.Empty() {
  29. return errors.New("Signature or Key missing")
  30. }
  31. if !s.Sig.Empty() {
  32. return errors.New("Transaction can only be signed once")
  33. }
  34. // set the value once we are happy
  35. s.Signed = Signed{sig, pubkey}
  36. return nil
  37. }
  38. // Signers will return the public key(s) that signed if the signature
  39. // is valid, or an error if there is any issue with the signature,
  40. // including if there are no signatures
  41. func (s *OneSig) Signers() ([]crypto.PubKey, error) {
  42. if s.Pubkey.Empty() || s.Sig.Empty() {
  43. return nil, errors.New("Never signed")
  44. }
  45. if !s.Pubkey.VerifyBytes(s.Data, s.Sig) {
  46. return nil, errors.New("Signature doesn't match")
  47. }
  48. return []crypto.PubKey{s.Pubkey}, nil
  49. }