lotus/chain/types/signature.go
2019-11-17 11:00:45 -06:00

122 lines
2.1 KiB
Go

package types
import (
"bytes"
"encoding/binary"
"fmt"
"io"
cbg "github.com/whyrusleeping/cbor-gen"
)
const SignatureMaxLength = 200
const (
KTSecp256k1 = "secp256k1"
KTBLS = "bls"
)
const (
IKTUnknown = -1
IKTSecp256k1 = iota
IKTBLS
)
type Signature struct {
Type string
Data []byte
}
func SignatureFromBytes(x []byte) (Signature, error) {
val, nr := binary.Uvarint(x)
if nr != 1 {
return Signature{}, fmt.Errorf("signatures with type field longer than one byte are invalid")
}
var ts string
switch val {
case IKTSecp256k1:
ts = KTSecp256k1
case IKTBLS:
ts = KTBLS
default:
return Signature{}, fmt.Errorf("unsupported signature type: %d", val)
}
return Signature{
Type: ts,
Data: x[1:],
}, nil
}
func (s *Signature) TypeCode() int {
switch s.Type {
case KTSecp256k1:
return IKTSecp256k1
case KTBLS:
return IKTBLS
default:
log.Errorf("called TypeCode on signature with unknown Type: %q", s.Type)
return IKTUnknown
}
}
func (s *Signature) MarshalCBOR(w io.Writer) error {
if s == nil {
_, err := w.Write(cbg.CborNull)
return err
}
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1))
if _, err := w.Write(header); err != nil {
return err
}
if _, err := w.Write([]byte{byte(s.TypeCode())}); err != nil {
return err
}
if _, err := w.Write(s.Data); err != nil {
return err
}
return nil
}
func (s *Signature) UnmarshalCBOR(br io.Reader) error {
maj, l, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajByteString {
return fmt.Errorf("cbor input for signature was not a byte string")
}
if l > SignatureMaxLength {
return fmt.Errorf("cbor byte array for signature was too long")
}
buf := make([]byte, l)
if _, err := io.ReadFull(br, buf); err != nil {
return err
}
switch buf[0] {
default:
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
case IKTSecp256k1:
s.Type = KTSecp256k1
case IKTBLS:
s.Type = KTBLS
}
s.Data = buf[1:]
return nil
}
func (s *Signature) Equals(o *Signature) bool {
return s.Type == o.Type && bytes.Equal(s.Data, o.Data)
}