github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/transaction/signer.go (about) 1 package transaction 2 3 import ( 4 "errors" 5 "math/big" 6 7 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 8 "github.com/nspcc-dev/neo-go/pkg/io" 9 "github.com/nspcc-dev/neo-go/pkg/util" 10 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 11 ) 12 13 // The maximum number of AllowedContracts or AllowedGroups. 14 const maxSubitems = 16 15 16 // Signer implements a Transaction signer. 17 type Signer struct { 18 Account util.Uint160 `json:"account"` 19 Scopes WitnessScope `json:"scopes"` 20 AllowedContracts []util.Uint160 `json:"allowedcontracts,omitempty"` 21 AllowedGroups []*keys.PublicKey `json:"allowedgroups,omitempty"` 22 Rules []WitnessRule `json:"rules,omitempty"` 23 } 24 25 // EncodeBinary implements the Serializable interface. 26 func (c *Signer) EncodeBinary(bw *io.BinWriter) { 27 bw.WriteBytes(c.Account[:]) 28 bw.WriteB(byte(c.Scopes)) 29 if c.Scopes&CustomContracts != 0 { 30 bw.WriteArray(c.AllowedContracts) 31 } 32 if c.Scopes&CustomGroups != 0 { 33 bw.WriteArray(c.AllowedGroups) 34 } 35 if c.Scopes&Rules != 0 { 36 bw.WriteArray(c.Rules) 37 } 38 } 39 40 // DecodeBinary implements the Serializable interface. 41 func (c *Signer) DecodeBinary(br *io.BinReader) { 42 br.ReadBytes(c.Account[:]) 43 c.Scopes = WitnessScope(br.ReadB()) 44 if c.Scopes & ^(Global|CalledByEntry|CustomContracts|CustomGroups|Rules|None) != 0 { 45 br.Err = errors.New("unknown witness scope") 46 return 47 } 48 if c.Scopes&Global != 0 && c.Scopes != Global { 49 br.Err = errors.New("global scope can not be combined with other scopes") 50 return 51 } 52 if c.Scopes&CustomContracts != 0 { 53 br.ReadArray(&c.AllowedContracts, maxSubitems) 54 } 55 if c.Scopes&CustomGroups != 0 { 56 br.ReadArray(&c.AllowedGroups, maxSubitems) 57 } 58 if c.Scopes&Rules != 0 { 59 br.ReadArray(&c.Rules, maxSubitems) 60 } 61 } 62 63 // SignersToStackItem converts transaction.Signers to stackitem.Item. 64 func SignersToStackItem(signers []Signer) stackitem.Item { 65 res := make([]stackitem.Item, len(signers)) 66 for i, s := range signers { 67 contracts := make([]stackitem.Item, len(s.AllowedContracts)) 68 for j, c := range s.AllowedContracts { 69 contracts[j] = stackitem.NewByteArray(c.BytesBE()) 70 } 71 groups := make([]stackitem.Item, len(s.AllowedGroups)) 72 for j, g := range s.AllowedGroups { 73 groups[j] = stackitem.NewByteArray(g.Bytes()) 74 } 75 rules := make([]stackitem.Item, len(s.Rules)) 76 for j, r := range s.Rules { 77 rules[j] = r.ToStackItem() 78 } 79 res[i] = stackitem.NewArray([]stackitem.Item{ 80 stackitem.NewByteArray(s.Account.BytesBE()), 81 stackitem.NewBigInteger(big.NewInt(int64(s.Scopes))), 82 stackitem.NewArray(contracts), 83 stackitem.NewArray(groups), 84 stackitem.NewArray(rules), 85 }) 86 } 87 return stackitem.NewArray(res) 88 } 89 90 // Copy creates a deep copy of the Signer. 91 func (c *Signer) Copy() *Signer { 92 if c == nil { 93 return nil 94 } 95 cp := *c 96 if c.AllowedContracts != nil { 97 cp.AllowedContracts = make([]util.Uint160, len(c.AllowedContracts)) 98 copy(cp.AllowedContracts, c.AllowedContracts) 99 } 100 cp.AllowedGroups = keys.PublicKeys(c.AllowedGroups).Copy() 101 if c.Rules != nil { 102 cp.Rules = make([]WitnessRule, len(c.Rules)) 103 for i, rule := range c.Rules { 104 cp.Rules[i] = *rule.Copy() 105 } 106 } 107 108 return &cp 109 }