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.

67 lines
1.7 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. // MultiSig 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 MultiSig struct {
  12. Data data.Bytes
  13. Sigs []Signed
  14. }
  15. type Signed struct {
  16. Sig crypto.Signature
  17. Pubkey crypto.PubKey
  18. }
  19. var _ SigInner = &MultiSig{}
  20. func NewMulti(data []byte) Sig {
  21. return Sig{&MultiSig{Data: data}}
  22. }
  23. // SignBytes returns the original data passed into `NewSig`
  24. func (s *MultiSig) SignBytes() []byte {
  25. return s.Data
  26. }
  27. // Sign will add a signature and pubkey.
  28. //
  29. // Depending on the Signable, one may be able to call this multiple times for multisig
  30. // Returns error if called with invalid data or too many times
  31. func (s *MultiSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error {
  32. if pubkey.Empty() || sig.Empty() {
  33. return errors.New("Signature or Key missing")
  34. }
  35. // set the value once we are happy
  36. x := Signed{sig, pubkey}
  37. s.Sigs = append(s.Sigs, x)
  38. return nil
  39. }
  40. // Signers will return the public key(s) that signed if the signature
  41. // is valid, or an error if there is any issue with the signature,
  42. // including if there are no signatures
  43. func (s *MultiSig) Signers() ([]crypto.PubKey, error) {
  44. if len(s.Sigs) == 0 {
  45. return nil, errors.New("Never signed")
  46. }
  47. keys := make([]crypto.PubKey, len(s.Sigs))
  48. for i := range s.Sigs {
  49. ms := s.Sigs[i]
  50. if !ms.Pubkey.VerifyBytes(s.Data, ms.Sig) {
  51. return nil, errors.Errorf("Signature %d doesn't match (key: %X)", i, ms.Pubkey.Bytes())
  52. }
  53. keys[i] = ms.Pubkey
  54. }
  55. return keys, nil
  56. }