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  }