neoneo-go/pkg/smartcontract/contract.go
Roman Khimov 8d4dd2d2e1 vm: move opcodes into their own package
This allows easier reuse of opcodes and in some cases allows to eliminate
dependencies on the whole vm package, like in compiler that only needs opcodes
and doesn't care about VM for any other purpose.

And yes, they're opcodes because an instruction is a whole thing with
operands, that's what context.Next() returns.
2019-12-03 18:22:14 +03:00

58 lines
1.5 KiB
Go

package smartcontract
import (
"bytes"
"fmt"
"sort"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/vm"
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
)
// CreateSignatureRedeemScript creates a check signature script runnable by VM.
func CreateSignatureRedeemScript(key *keys.PublicKey) ([]byte, error) {
buf := new(bytes.Buffer)
err := vm.EmitBytes(buf, key.Bytes())
if err != nil {
return nil, err
}
err = vm.EmitOpcode(buf, opcode.CHECKSIG)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// CreateMultiSigRedeemScript creates a script runnable by the VM.
func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, error) {
if m <= 1 {
return nil, fmt.Errorf("param m cannot be smaller or equal to 1 got %d", m)
}
if m > len(publicKeys) {
return nil, fmt.Errorf("length of the signatures (%d) is higher then the number of public keys", m)
}
if m > 1024 {
return nil, fmt.Errorf("public key count %d exceeds maximum of length 1024", len(publicKeys))
}
buf := new(bytes.Buffer)
if err := vm.EmitInt(buf, int64(m)); err != nil {
return nil, err
}
sort.Sort(publicKeys)
for _, pubKey := range publicKeys {
if err := vm.EmitBytes(buf, pubKey.Bytes()); err != nil {
return nil, err
}
}
if err := vm.EmitInt(buf, int64(len(publicKeys))); err != nil {
return nil, err
}
if err := vm.EmitOpcode(buf, opcode.CHECKMULTISIG); err != nil {
return nil, err
}
return buf.Bytes(), nil
}