package contract import ( "crypto/elliptic" "errors" "math" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core/fee" "github.com/nspcc-dev/neo-go/pkg/core/interop" "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/vm/stackitem" ) // CreateMultisigAccount calculates multisig contract scripthash for a // given m and a set of public keys. func CreateMultisigAccount(ic *interop.Context) error { m := ic.VM.Estack().Pop().BigInt() mu64 := m.Uint64() if !m.IsUint64() || mu64 > math.MaxInt32 { return errors.New("m must be positive and fit int32") } arr := ic.VM.Estack().Pop().Array() pubs := make(keys.PublicKeys, len(arr)) for i, pk := range arr { p, err := keys.NewPublicKeyFromBytes(pk.Value().([]byte), elliptic.P256()) if err != nil { return err } pubs[i] = p } var invokeFee int64 if ic.IsHardforkEnabled(config.HFAspidochelone) { invokeFee = fee.ECDSAVerifyPrice * int64(len(pubs)) } else { invokeFee = 1 << 8 } invokeFee *= ic.BaseExecFee() if !ic.VM.AddGas(invokeFee) { return errors.New("gas limit exceeded") } script, err := smartcontract.CreateMultiSigRedeemScript(int(mu64), pubs) if err != nil { return err } ic.VM.Estack().PushItem(stackitem.NewByteArray(hash.Hash160(script).BytesBE())) return nil } // CreateStandardAccount calculates contract scripthash for a given public key. func CreateStandardAccount(ic *interop.Context) error { h := ic.VM.Estack().Pop().Bytes() p, err := keys.NewPublicKeyFromBytes(h, elliptic.P256()) if err != nil { return err } var invokeFee int64 if ic.IsHardforkEnabled(config.HFAspidochelone) { invokeFee = fee.ECDSAVerifyPrice } else { invokeFee = 1 << 8 } invokeFee *= ic.BaseExecFee() if !ic.VM.AddGas(invokeFee) { return errors.New("gas limit exceeded") } ic.VM.Estack().PushItem(stackitem.NewByteArray(p.GetScriptHash().BytesBE())) return nil }