github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/smartcontract/contract.go (about)

     1  package smartcontract
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
     8  	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
     9  	"github.com/nspcc-dev/neo-go/pkg/io"
    10  	"github.com/nspcc-dev/neo-go/pkg/vm/emit"
    11  )
    12  
    13  // CreateMultiSigRedeemScript creates an "m out of n" type verification script
    14  // where n is the length of publicKeys.
    15  func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, error) {
    16  	if m < 1 {
    17  		return nil, fmt.Errorf("param m cannot be smaller than 1, got %d", m)
    18  	}
    19  	if m > len(publicKeys) {
    20  		return nil, fmt.Errorf("length of the signatures (%d) is higher then the number of public keys", m)
    21  	}
    22  	if m > 1024 {
    23  		return nil, fmt.Errorf("public key count %d exceeds maximum of length 1024", len(publicKeys))
    24  	}
    25  
    26  	buf := io.NewBufBinWriter()
    27  	emit.Int(buf.BinWriter, int64(m))
    28  	sort.Sort(publicKeys)
    29  	for _, pubKey := range publicKeys {
    30  		emit.Bytes(buf.BinWriter, pubKey.Bytes())
    31  	}
    32  	emit.Int(buf.BinWriter, int64(len(publicKeys)))
    33  	emit.Syscall(buf.BinWriter, interopnames.SystemCryptoCheckMultisig)
    34  
    35  	return buf.Bytes(), nil
    36  }
    37  
    38  // CreateDefaultMultiSigRedeemScript creates an "m out of n" type verification script
    39  // using publicKeys length with the default BFT assumptions of (n - (n-1)/3) for m.
    40  func CreateDefaultMultiSigRedeemScript(publicKeys keys.PublicKeys) ([]byte, error) {
    41  	n := len(publicKeys)
    42  	m := GetDefaultHonestNodeCount(n)
    43  	return CreateMultiSigRedeemScript(m, publicKeys)
    44  }
    45  
    46  // CreateMajorityMultiSigRedeemScript creates an "m out of n" type verification script
    47  // using publicKeys length with m set to majority.
    48  func CreateMajorityMultiSigRedeemScript(publicKeys keys.PublicKeys) ([]byte, error) {
    49  	n := len(publicKeys)
    50  	m := GetMajorityHonestNodeCount(n)
    51  	return CreateMultiSigRedeemScript(m, publicKeys)
    52  }
    53  
    54  // GetDefaultHonestNodeCount returns minimum number of honest nodes
    55  // required for network of size n.
    56  func GetDefaultHonestNodeCount(n int) int {
    57  	return n - (n-1)/3
    58  }
    59  
    60  // GetMajorityHonestNodeCount returns minimum number of honest nodes
    61  // required for majority-style agreement.
    62  func GetMajorityHonestNodeCount(n int) int {
    63  	return n - (n-1)/2
    64  }