diff --git a/pkg/smartcontract/manifest/group.go b/pkg/smartcontract/manifest/group.go new file mode 100644 index 000000000..96d02eaf0 --- /dev/null +++ b/pkg/smartcontract/manifest/group.go @@ -0,0 +1,95 @@ +package manifest + +import ( + "crypto/elliptic" + "encoding/hex" + "encoding/json" + "errors" + + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" +) + +// Group represents a group of smartcontracts identified by a public key. +// Every SC in a group must provide signature of it's hash to prove +// it belongs to a group. +type Group struct { + PublicKey *keys.PublicKey `json:"pubkey"` + Signature []byte `json:"signature"` +} + +type groupAux struct { + PublicKey string `json:"pubkey"` + Signature []byte `json:"signature"` +} + +// IsValid checks whether group's signature corresponds to the given hash. +func (g *Group) IsValid(h util.Uint160) error { + if !g.PublicKey.Verify(g.Signature, hash.Sha256(h.BytesBE()).BytesBE()) { + return errors.New("incorrect group signature") + } + return nil +} + +// MarshalJSON implements json.Marshaler interface. +func (g *Group) MarshalJSON() ([]byte, error) { + aux := &groupAux{ + PublicKey: hex.EncodeToString(g.PublicKey.Bytes()), + Signature: g.Signature, + } + return json.Marshal(aux) +} + +// UnmarshalJSON implements json.Unmarshaler interface. +func (g *Group) UnmarshalJSON(data []byte) error { + aux := new(groupAux) + if err := json.Unmarshal(data, aux); err != nil { + return err + } + b, err := hex.DecodeString(aux.PublicKey) + if err != nil { + return err + } + pub := new(keys.PublicKey) + if err := pub.DecodeBytes(b); err != nil { + return err + } + g.PublicKey = pub + g.Signature = aux.Signature + return nil +} + +// ToStackItem converts Group to stackitem.Item. +func (g *Group) ToStackItem() stackitem.Item { + return stackitem.NewStruct([]stackitem.Item{ + stackitem.NewByteArray(g.PublicKey.Bytes()), + stackitem.NewByteArray(g.Signature), + }) +} + +// FromStackItem converts stackitem.Item to Group. +func (g *Group) FromStackItem(item stackitem.Item) error { + if item.Type() != stackitem.StructT { + return errors.New("invalid Group stackitem type") + } + group := item.Value().([]stackitem.Item) + if len(group) != 2 { + return errors.New("invalid Group stackitem length") + } + pKey, err := group[0].TryBytes() + if err != nil { + return err + } + g.PublicKey, err = keys.NewPublicKeyFromBytes(pKey, elliptic.P256()) + if err != nil { + return err + } + sig, err := group[1].TryBytes() + if err != nil { + return err + } + g.Signature = sig + return nil +} diff --git a/pkg/smartcontract/manifest/method.go b/pkg/smartcontract/manifest/method.go index e56a89165..f6e99175f 100644 --- a/pkg/smartcontract/manifest/method.go +++ b/pkg/smartcontract/manifest/method.go @@ -1,15 +1,9 @@ package manifest import ( - "crypto/elliptic" - "encoding/hex" - "encoding/json" "errors" - "github.com/nspcc-dev/neo-go/pkg/crypto/hash" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -25,19 +19,6 @@ type Event struct { Parameters []Parameter `json:"parameters"` } -// Group represents a group of smartcontracts identified by a public key. -// Every SC in a group must provide signature of it's hash to prove -// it belongs to a group. -type Group struct { - PublicKey *keys.PublicKey `json:"pubkey"` - Signature []byte `json:"signature"` -} - -type groupAux struct { - PublicKey string `json:"pubkey"` - Signature []byte `json:"signature"` -} - // Method represents method's metadata. type Method struct { Name string `json:"name"` @@ -55,75 +36,6 @@ func NewParameter(name string, typ smartcontract.ParamType) Parameter { } } -// IsValid checks whether group's signature corresponds to the given hash. -func (g *Group) IsValid(h util.Uint160) error { - if !g.PublicKey.Verify(g.Signature, hash.Sha256(h.BytesBE()).BytesBE()) { - return errors.New("incorrect group signature") - } - return nil -} - -// MarshalJSON implements json.Marshaler interface. -func (g *Group) MarshalJSON() ([]byte, error) { - aux := &groupAux{ - PublicKey: hex.EncodeToString(g.PublicKey.Bytes()), - Signature: g.Signature, - } - return json.Marshal(aux) -} - -// UnmarshalJSON implements json.Unmarshaler interface. -func (g *Group) UnmarshalJSON(data []byte) error { - aux := new(groupAux) - if err := json.Unmarshal(data, aux); err != nil { - return err - } - b, err := hex.DecodeString(aux.PublicKey) - if err != nil { - return err - } - pub := new(keys.PublicKey) - if err := pub.DecodeBytes(b); err != nil { - return err - } - g.PublicKey = pub - g.Signature = aux.Signature - return nil -} - -// ToStackItem converts Group to stackitem.Item. -func (g *Group) ToStackItem() stackitem.Item { - return stackitem.NewStruct([]stackitem.Item{ - stackitem.NewByteArray(g.PublicKey.Bytes()), - stackitem.NewByteArray(g.Signature), - }) -} - -// FromStackItem converts stackitem.Item to Group. -func (g *Group) FromStackItem(item stackitem.Item) error { - if item.Type() != stackitem.StructT { - return errors.New("invalid Group stackitem type") - } - group := item.Value().([]stackitem.Item) - if len(group) != 2 { - return errors.New("invalid Group stackitem length") - } - pKey, err := group[0].TryBytes() - if err != nil { - return err - } - g.PublicKey, err = keys.NewPublicKeyFromBytes(pKey, elliptic.P256()) - if err != nil { - return err - } - sig, err := group[1].TryBytes() - if err != nil { - return err - } - g.Signature = sig - return nil -} - // ToStackItem converts Method to stackitem.Item. func (m *Method) ToStackItem() stackitem.Item { params := make([]stackitem.Item, len(m.Parameters))