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.
This commit is contained in:
parent
f48228ef7d
commit
8d4dd2d2e1
21 changed files with 1285 additions and 1248 deletions
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/CityOfZion/neo-go/pkg/wallet"
|
||||
"github.com/nspcc-dev/dbft"
|
||||
"github.com/nspcc-dev/dbft/block"
|
||||
|
@ -283,7 +283,7 @@ func (s *service) getBlockWitness(b *core.Block) *transaction.Witness {
|
|||
var invoc []byte
|
||||
for i, j := 0, 0; i < len(pubs) && j < m; i++ {
|
||||
if sig, ok := sigs[pubs[i]]; ok {
|
||||
invoc = append(invoc, byte(vm.PUSHBYTES64))
|
||||
invoc = append(invoc, byte(opcode.PUSHBYTES64))
|
||||
invoc = append(invoc, sig...)
|
||||
j++
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/nspcc-dev/dbft/payload"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -193,7 +194,7 @@ func (p *Payload) Sign(key *privateKey) error {
|
|||
return err
|
||||
}
|
||||
|
||||
p.Witness.InvocationScript = append([]byte{byte(vm.PUSHBYTES64)}, sig...)
|
||||
p.Witness.InvocationScript = append([]byte{byte(opcode.PUSHBYTES64)}, sig...)
|
||||
p.Witness.VerificationScript = verif
|
||||
|
||||
return nil
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
// createGenesisBlock creates a genesis block based on the given configuration.
|
||||
|
@ -33,7 +33,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) {
|
|||
NextConsensus: nextConsensus,
|
||||
Script: &transaction.Witness{
|
||||
InvocationScript: []byte{},
|
||||
VerificationScript: []byte{byte(vm.PUSHT)},
|
||||
VerificationScript: []byte{byte(opcode.PUSHT)},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) {
|
|||
Scripts: []*transaction.Witness{
|
||||
{
|
||||
InvocationScript: []byte{},
|
||||
VerificationScript: []byte{byte(vm.PUSHT)},
|
||||
VerificationScript: []byte{byte(opcode.PUSHT)},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -92,7 +92,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) {
|
|||
}
|
||||
|
||||
func governingTokenTX() *transaction.Transaction {
|
||||
admin := hash.Hash160([]byte{byte(vm.PUSHT)})
|
||||
admin := hash.Hash160([]byte{byte(opcode.PUSHT)})
|
||||
registerTX := &transaction.RegisterTX{
|
||||
AssetType: transaction.GoverningToken,
|
||||
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]",
|
||||
|
@ -115,7 +115,7 @@ func governingTokenTX() *transaction.Transaction {
|
|||
}
|
||||
|
||||
func utilityTokenTX() *transaction.Transaction {
|
||||
admin := hash.Hash160([]byte{byte(vm.PUSHF)})
|
||||
admin := hash.Hash160([]byte{byte(opcode.PUSHF)})
|
||||
registerTX := &transaction.RegisterTX{
|
||||
AssetType: transaction.UtilityToken,
|
||||
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
errs "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -281,7 +282,7 @@ func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byt
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = vm.EmitOpcode(script, vm.PACK)
|
||||
err = vm.EmitOpcode(script, opcode.PACK)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"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.
|
||||
|
@ -16,7 +17,7 @@ func CreateSignatureRedeemScript(key *keys.PublicKey) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = vm.EmitOpcode(buf, vm.CHECKSIG)
|
||||
err = vm.EmitOpcode(buf, opcode.CHECKSIG)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -49,7 +50,7 @@ func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, erro
|
|||
if err := vm.EmitInt(buf, int64(len(publicKeys))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := vm.EmitOpcode(buf, vm.CHECKMULTISIG); err != nil {
|
||||
if err := vm.EmitOpcode(buf, opcode.CHECKMULTISIG); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -24,7 +24,7 @@ func TestCreateMultiSigRedeemScript(t *testing.T) {
|
|||
br := io.NewBinReaderFromBuf(out)
|
||||
var b uint8
|
||||
br.ReadLE(&b)
|
||||
assert.Equal(t, vm.PUSH3, vm.Instruction(b))
|
||||
assert.Equal(t, opcode.PUSH3, opcode.Opcode(b))
|
||||
|
||||
for i := 0; i < len(validators); i++ {
|
||||
bb := br.ReadBytes()
|
||||
|
@ -35,7 +35,7 @@ func TestCreateMultiSigRedeemScript(t *testing.T) {
|
|||
}
|
||||
|
||||
br.ReadLE(&b)
|
||||
assert.Equal(t, vm.PUSH3, vm.Instruction(b))
|
||||
assert.Equal(t, opcode.PUSH3, opcode.Opcode(b))
|
||||
br.ReadLE(&b)
|
||||
assert.Equal(t, vm.CHECKMULTISIG, vm.Instruction(b))
|
||||
assert.Equal(t, opcode.CHECKMULTISIG, opcode.Opcode(b))
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
// The identifier of the entry function. Default set to Main.
|
||||
|
@ -95,13 +95,13 @@ func (c *codegen) emitLoadLocal(name string) {
|
|||
}
|
||||
|
||||
func (c *codegen) emitLoadLocalPos(pos int) {
|
||||
emitOpcode(c.prog.BinWriter, vm.DUPFROMALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DUPFROMALTSTACK)
|
||||
emitInt(c.prog.BinWriter, int64(pos))
|
||||
emitOpcode(c.prog.BinWriter, vm.PICKITEM)
|
||||
emitOpcode(c.prog.BinWriter, opcode.PICKITEM)
|
||||
}
|
||||
|
||||
func (c *codegen) emitStoreLocal(pos int) {
|
||||
emitOpcode(c.prog.BinWriter, vm.DUPFROMALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DUPFROMALTSTACK)
|
||||
|
||||
if pos < 0 {
|
||||
c.prog.Err = fmt.Errorf("invalid position to store local: %d", pos)
|
||||
|
@ -110,19 +110,19 @@ func (c *codegen) emitStoreLocal(pos int) {
|
|||
|
||||
emitInt(c.prog.BinWriter, int64(pos))
|
||||
emitInt(c.prog.BinWriter, 2)
|
||||
emitOpcode(c.prog.BinWriter, vm.ROLL)
|
||||
emitOpcode(c.prog.BinWriter, vm.SETITEM)
|
||||
emitOpcode(c.prog.BinWriter, opcode.ROLL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SETITEM)
|
||||
}
|
||||
|
||||
func (c *codegen) emitLoadField(i int) {
|
||||
emitInt(c.prog.BinWriter, int64(i))
|
||||
emitOpcode(c.prog.BinWriter, vm.PICKITEM)
|
||||
emitOpcode(c.prog.BinWriter, opcode.PICKITEM)
|
||||
}
|
||||
|
||||
func (c *codegen) emitStoreStructField(i int) {
|
||||
emitInt(c.prog.BinWriter, int64(i))
|
||||
emitOpcode(c.prog.BinWriter, vm.ROT)
|
||||
emitOpcode(c.prog.BinWriter, vm.SETITEM)
|
||||
emitOpcode(c.prog.BinWriter, opcode.ROT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SETITEM)
|
||||
}
|
||||
|
||||
// convertGlobals traverses the AST and only converts global declarations.
|
||||
|
@ -163,8 +163,8 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl) {
|
|||
// All globals copied into the scope of the function need to be added
|
||||
// to the stack size of the function.
|
||||
emitInt(c.prog.BinWriter, f.stackSize()+countGlobals(file))
|
||||
emitOpcode(c.prog.BinWriter, vm.NEWARRAY)
|
||||
emitOpcode(c.prog.BinWriter, vm.TOALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NEWARRAY)
|
||||
emitOpcode(c.prog.BinWriter, opcode.TOALTSTACK)
|
||||
|
||||
// We need to handle methods, which in Go, is just syntactic sugar.
|
||||
// The method receiver will be passed in as first argument.
|
||||
|
@ -202,9 +202,9 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl) {
|
|||
|
||||
// If this function returns the void (no return stmt) we will cleanup its junk on the stack.
|
||||
if !hasReturnStmt(decl) {
|
||||
emitOpcode(c.prog.BinWriter, vm.FROMALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, vm.DROP)
|
||||
emitOpcode(c.prog.BinWriter, vm.RET)
|
||||
emitOpcode(c.prog.BinWriter, opcode.FROMALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DROP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.RET)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,9 +295,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
ast.Walk(c, n.Results[0])
|
||||
}
|
||||
|
||||
emitOpcode(c.prog.BinWriter, vm.FROMALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, vm.DROP) // Cleanup the stack.
|
||||
emitOpcode(c.prog.BinWriter, vm.RET)
|
||||
emitOpcode(c.prog.BinWriter, opcode.FROMALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DROP) // Cleanup the stack.
|
||||
emitOpcode(c.prog.BinWriter, opcode.RET)
|
||||
return nil
|
||||
|
||||
case *ast.IfStmt:
|
||||
|
@ -307,13 +307,13 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
|
||||
if n.Cond != nil {
|
||||
ast.Walk(c, n.Cond)
|
||||
emitJmp(c.prog.BinWriter, vm.JMPIFNOT, int16(lElse))
|
||||
emitJmp(c.prog.BinWriter, opcode.JMPIFNOT, int16(lElse))
|
||||
}
|
||||
|
||||
c.setLabel(lIf)
|
||||
ast.Walk(c, n.Body)
|
||||
if n.Else != nil {
|
||||
emitJmp(c.prog.BinWriter, vm.JMP, int16(lElseEnd))
|
||||
emitJmp(c.prog.BinWriter, opcode.JMP, int16(lElseEnd))
|
||||
}
|
||||
|
||||
c.setLabel(lElse)
|
||||
|
@ -359,7 +359,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
c.emitLoadConst(c.typeInfo.Types[n.Elts[i]])
|
||||
}
|
||||
emitInt(c.prog.BinWriter, int64(ln))
|
||||
emitOpcode(c.prog.BinWriter, vm.PACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.PACK)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -374,13 +374,13 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
switch n.Op {
|
||||
case token.LAND:
|
||||
ast.Walk(c, n.X)
|
||||
emitJmp(c.prog.BinWriter, vm.JMPIFNOT, int16(len(c.l)-1))
|
||||
emitJmp(c.prog.BinWriter, opcode.JMPIFNOT, int16(len(c.l)-1))
|
||||
ast.Walk(c, n.Y)
|
||||
return nil
|
||||
|
||||
case token.LOR:
|
||||
ast.Walk(c, n.X)
|
||||
emitJmp(c.prog.BinWriter, vm.JMPIF, int16(len(c.l)-3))
|
||||
emitJmp(c.prog.BinWriter, opcode.JMPIF, int16(len(c.l)-3))
|
||||
ast.Walk(c, n.Y)
|
||||
return nil
|
||||
|
||||
|
@ -405,24 +405,24 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
case n.Op == token.ADD:
|
||||
// VM has separate opcodes for number and string concatenation
|
||||
if isStringType(tinfo.Type) {
|
||||
emitOpcode(c.prog.BinWriter, vm.CAT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.CAT)
|
||||
} else {
|
||||
emitOpcode(c.prog.BinWriter, vm.ADD)
|
||||
emitOpcode(c.prog.BinWriter, opcode.ADD)
|
||||
}
|
||||
case n.Op == token.EQL:
|
||||
// VM has separate opcodes for number and string equality
|
||||
if isStringType(c.typeInfo.Types[n.X].Type) {
|
||||
emitOpcode(c.prog.BinWriter, vm.EQUAL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.EQUAL)
|
||||
} else {
|
||||
emitOpcode(c.prog.BinWriter, vm.NUMEQUAL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NUMEQUAL)
|
||||
}
|
||||
case n.Op == token.NEQ:
|
||||
// VM has separate opcodes for number and string equality
|
||||
if isStringType(c.typeInfo.Types[n.X].Type) {
|
||||
emitOpcode(c.prog.BinWriter, vm.EQUAL)
|
||||
emitOpcode(c.prog.BinWriter, vm.NOT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.EQUAL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NOT)
|
||||
} else {
|
||||
emitOpcode(c.prog.BinWriter, vm.NUMNOTEQUAL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NUMNOTEQUAL)
|
||||
}
|
||||
default:
|
||||
c.convertToken(n.Op)
|
||||
|
@ -478,14 +478,14 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
// Do not swap for builtin functions.
|
||||
if !isBuiltin {
|
||||
if numArgs == 2 {
|
||||
emitOpcode(c.prog.BinWriter, vm.SWAP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SWAP)
|
||||
} else if numArgs == 3 {
|
||||
emitInt(c.prog.BinWriter, 2)
|
||||
emitOpcode(c.prog.BinWriter, vm.XSWAP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.XSWAP)
|
||||
} else {
|
||||
for i := 1; i < numArgs; i++ {
|
||||
emitInt(c.prog.BinWriter, int64(i))
|
||||
emitOpcode(c.prog.BinWriter, vm.ROLL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.ROLL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
case isSyscall(f):
|
||||
c.convertSyscall(f.selector.Name, f.name)
|
||||
default:
|
||||
emitCall(c.prog.BinWriter, vm.CALL, int16(f.label))
|
||||
emitCall(c.prog.BinWriter, opcode.CALL, int16(f.label))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -529,11 +529,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
case token.ADD:
|
||||
// +10 == 10, no need to do anything in this case
|
||||
case token.SUB:
|
||||
emitOpcode(c.prog.BinWriter, vm.NEGATE)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NEGATE)
|
||||
case token.NOT:
|
||||
emitOpcode(c.prog.BinWriter, vm.NOT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NOT)
|
||||
case token.XOR:
|
||||
emitOpcode(c.prog.BinWriter, vm.INVERT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.INVERT)
|
||||
default:
|
||||
c.prog.Err = fmt.Errorf("invalid unary operator: %s", n.Op)
|
||||
return nil
|
||||
|
@ -565,7 +565,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
c.emitLoadField(int(val))
|
||||
default:
|
||||
ast.Walk(c, n.Index)
|
||||
emitOpcode(c.prog.BinWriter, vm.PICKITEM) // just pickitem here
|
||||
emitOpcode(c.prog.BinWriter, opcode.PICKITEM) // just pickitem here
|
||||
}
|
||||
return nil
|
||||
|
||||
|
@ -583,14 +583,14 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
ast.Walk(c, n.Cond)
|
||||
|
||||
// Jump if the condition is false
|
||||
emitJmp(c.prog.BinWriter, vm.JMPIFNOT, int16(fend))
|
||||
emitJmp(c.prog.BinWriter, opcode.JMPIFNOT, int16(fend))
|
||||
|
||||
// Walk body followed by the iterator (post stmt).
|
||||
ast.Walk(c, n.Body)
|
||||
ast.Walk(c, n.Post)
|
||||
|
||||
// Jump back to condition.
|
||||
emitJmp(c.prog.BinWriter, vm.JMP, int16(fstart))
|
||||
emitJmp(c.prog.BinWriter, opcode.JMP, int16(fstart))
|
||||
c.setLabel(fend)
|
||||
|
||||
return nil
|
||||
|
@ -616,7 +616,7 @@ func (c *codegen) convertSyscall(api, name string) {
|
|||
|
||||
// This NOP instruction is basically not needed, but if we do, we have a
|
||||
// one to one matching avm file with neo-python which is very nice for debugging.
|
||||
emitOpcode(c.prog.BinWriter, vm.NOP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NOP)
|
||||
}
|
||||
|
||||
func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||
|
@ -633,32 +633,32 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
|||
arg := expr.Args[0]
|
||||
typ := c.typeInfo.Types[arg].Type
|
||||
if isStringType(typ) {
|
||||
emitOpcode(c.prog.BinWriter, vm.SIZE)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SIZE)
|
||||
} else {
|
||||
emitOpcode(c.prog.BinWriter, vm.ARRAYSIZE)
|
||||
emitOpcode(c.prog.BinWriter, opcode.ARRAYSIZE)
|
||||
}
|
||||
case "append":
|
||||
arg := expr.Args[0]
|
||||
typ := c.typeInfo.Types[arg].Type
|
||||
if isByteArrayType(typ) {
|
||||
emitOpcode(c.prog.BinWriter, vm.CAT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.CAT)
|
||||
} else {
|
||||
emitOpcode(c.prog.BinWriter, vm.SWAP)
|
||||
emitOpcode(c.prog.BinWriter, vm.DUP)
|
||||
emitOpcode(c.prog.BinWriter, vm.PUSH2)
|
||||
emitOpcode(c.prog.BinWriter, vm.XSWAP)
|
||||
emitOpcode(c.prog.BinWriter, vm.APPEND)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SWAP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DUP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.PUSH2)
|
||||
emitOpcode(c.prog.BinWriter, opcode.XSWAP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.APPEND)
|
||||
}
|
||||
case "SHA256":
|
||||
emitOpcode(c.prog.BinWriter, vm.SHA256)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SHA256)
|
||||
case "SHA1":
|
||||
emitOpcode(c.prog.BinWriter, vm.SHA1)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SHA1)
|
||||
case "Hash256":
|
||||
emitOpcode(c.prog.BinWriter, vm.HASH256)
|
||||
emitOpcode(c.prog.BinWriter, opcode.HASH256)
|
||||
case "Hash160":
|
||||
emitOpcode(c.prog.BinWriter, vm.HASH160)
|
||||
emitOpcode(c.prog.BinWriter, opcode.HASH160)
|
||||
case "Equals":
|
||||
emitOpcode(c.prog.BinWriter, vm.EQUAL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.EQUAL)
|
||||
case "FromAddress":
|
||||
// We can be sure that this is a ast.BasicLit just containing a simple
|
||||
// address string. Note that the string returned from calling Value will
|
||||
|
@ -694,10 +694,10 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
|||
return
|
||||
}
|
||||
|
||||
emitOpcode(c.prog.BinWriter, vm.NOP)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NOP)
|
||||
emitInt(c.prog.BinWriter, int64(strct.NumFields()))
|
||||
emitOpcode(c.prog.BinWriter, vm.NEWSTRUCT)
|
||||
emitOpcode(c.prog.BinWriter, vm.TOALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NEWSTRUCT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.TOALTSTACK)
|
||||
|
||||
// We need to locally store all the fields, even if they are not initialized.
|
||||
// We will initialize all fields to their "zero" value.
|
||||
|
@ -730,55 +730,55 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
|||
c.emitLoadConst(typeAndVal)
|
||||
c.emitStoreLocal(i)
|
||||
}
|
||||
emitOpcode(c.prog.BinWriter, vm.FROMALTSTACK)
|
||||
emitOpcode(c.prog.BinWriter, opcode.FROMALTSTACK)
|
||||
}
|
||||
|
||||
func (c *codegen) convertToken(tok token.Token) {
|
||||
switch tok {
|
||||
case token.ADD_ASSIGN:
|
||||
emitOpcode(c.prog.BinWriter, vm.ADD)
|
||||
emitOpcode(c.prog.BinWriter, opcode.ADD)
|
||||
case token.SUB_ASSIGN:
|
||||
emitOpcode(c.prog.BinWriter, vm.SUB)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SUB)
|
||||
case token.MUL_ASSIGN:
|
||||
emitOpcode(c.prog.BinWriter, vm.MUL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.MUL)
|
||||
case token.QUO_ASSIGN:
|
||||
emitOpcode(c.prog.BinWriter, vm.DIV)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DIV)
|
||||
case token.ADD:
|
||||
emitOpcode(c.prog.BinWriter, vm.ADD)
|
||||
emitOpcode(c.prog.BinWriter, opcode.ADD)
|
||||
case token.SUB:
|
||||
emitOpcode(c.prog.BinWriter, vm.SUB)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SUB)
|
||||
case token.MUL:
|
||||
emitOpcode(c.prog.BinWriter, vm.MUL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.MUL)
|
||||
case token.QUO:
|
||||
emitOpcode(c.prog.BinWriter, vm.DIV)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DIV)
|
||||
case token.LSS:
|
||||
emitOpcode(c.prog.BinWriter, vm.LT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.LT)
|
||||
case token.LEQ:
|
||||
emitOpcode(c.prog.BinWriter, vm.LTE)
|
||||
emitOpcode(c.prog.BinWriter, opcode.LTE)
|
||||
case token.GTR:
|
||||
emitOpcode(c.prog.BinWriter, vm.GT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.GT)
|
||||
case token.GEQ:
|
||||
emitOpcode(c.prog.BinWriter, vm.GTE)
|
||||
emitOpcode(c.prog.BinWriter, opcode.GTE)
|
||||
case token.EQL:
|
||||
emitOpcode(c.prog.BinWriter, vm.NUMEQUAL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NUMEQUAL)
|
||||
case token.NEQ:
|
||||
emitOpcode(c.prog.BinWriter, vm.NUMNOTEQUAL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NUMNOTEQUAL)
|
||||
case token.DEC:
|
||||
emitOpcode(c.prog.BinWriter, vm.DEC)
|
||||
emitOpcode(c.prog.BinWriter, opcode.DEC)
|
||||
case token.INC:
|
||||
emitOpcode(c.prog.BinWriter, vm.INC)
|
||||
emitOpcode(c.prog.BinWriter, opcode.INC)
|
||||
case token.NOT:
|
||||
emitOpcode(c.prog.BinWriter, vm.NOT)
|
||||
emitOpcode(c.prog.BinWriter, opcode.NOT)
|
||||
case token.AND:
|
||||
emitOpcode(c.prog.BinWriter, vm.AND)
|
||||
emitOpcode(c.prog.BinWriter, opcode.AND)
|
||||
case token.OR:
|
||||
emitOpcode(c.prog.BinWriter, vm.OR)
|
||||
emitOpcode(c.prog.BinWriter, opcode.OR)
|
||||
case token.SHL:
|
||||
emitOpcode(c.prog.BinWriter, vm.SHL)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SHL)
|
||||
case token.SHR:
|
||||
emitOpcode(c.prog.BinWriter, vm.SHR)
|
||||
emitOpcode(c.prog.BinWriter, opcode.SHR)
|
||||
case token.XOR:
|
||||
emitOpcode(c.prog.BinWriter, vm.XOR)
|
||||
emitOpcode(c.prog.BinWriter, opcode.XOR)
|
||||
default:
|
||||
c.prog.Err = fmt.Errorf("compiler could not convert token: %s", tok)
|
||||
return
|
||||
|
@ -869,8 +869,8 @@ func (c *codegen) resolveFuncDecls(f *ast.File) {
|
|||
func (c *codegen) writeJumps(b []byte) {
|
||||
for i, op := range b {
|
||||
j := i + 1
|
||||
switch vm.Instruction(op) {
|
||||
case vm.JMP, vm.JMPIFNOT, vm.JMPIF, vm.CALL:
|
||||
switch opcode.Opcode(op) {
|
||||
case opcode.JMP, opcode.JMPIFNOT, opcode.JMPIF, opcode.CALL:
|
||||
index := int16(binary.LittleEndian.Uint16(b[j : j+2]))
|
||||
if int(index) > len(c.l) || int(index) < 0 {
|
||||
continue
|
||||
|
|
|
@ -8,40 +8,40 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
// emit a VM Instruction with data to the given buffer.
|
||||
func emit(w *io.BinWriter, instr vm.Instruction, b []byte) {
|
||||
func emit(w *io.BinWriter, instr opcode.Opcode, b []byte) {
|
||||
emitOpcode(w, instr)
|
||||
w.WriteBytes(b)
|
||||
}
|
||||
|
||||
// emitOpcode emits a single VM Instruction the given buffer.
|
||||
func emitOpcode(w *io.BinWriter, instr vm.Instruction) {
|
||||
func emitOpcode(w *io.BinWriter, instr opcode.Opcode) {
|
||||
w.WriteLE(byte(instr))
|
||||
}
|
||||
|
||||
// emitBool emits a bool type the given buffer.
|
||||
func emitBool(w *io.BinWriter, ok bool) {
|
||||
if ok {
|
||||
emitOpcode(w, vm.PUSHT)
|
||||
emitOpcode(w, opcode.PUSHT)
|
||||
return
|
||||
}
|
||||
emitOpcode(w, vm.PUSHF)
|
||||
emitOpcode(w, opcode.PUSHF)
|
||||
}
|
||||
|
||||
// emitInt emits a int type to the given buffer.
|
||||
func emitInt(w *io.BinWriter, i int64) {
|
||||
switch {
|
||||
case i == -1:
|
||||
emitOpcode(w, vm.PUSHM1)
|
||||
emitOpcode(w, opcode.PUSHM1)
|
||||
return
|
||||
case i == 0:
|
||||
emitOpcode(w, vm.PUSHF)
|
||||
emitOpcode(w, opcode.PUSHF)
|
||||
return
|
||||
case i > 0 && i < 16:
|
||||
val := vm.Instruction(int(vm.PUSH1) - 1 + int(i))
|
||||
val := opcode.Opcode(int(opcode.PUSH1) - 1 + int(i))
|
||||
emitOpcode(w, val)
|
||||
return
|
||||
}
|
||||
|
@ -61,19 +61,19 @@ func emitBytes(w *io.BinWriter, b []byte) {
|
|||
n := len(b)
|
||||
|
||||
switch {
|
||||
case n <= int(vm.PUSHBYTES75):
|
||||
emit(w, vm.Instruction(n), b)
|
||||
case n <= int(opcode.PUSHBYTES75):
|
||||
emit(w, opcode.Opcode(n), b)
|
||||
return
|
||||
case n < 0x100:
|
||||
emit(w, vm.PUSHDATA1, []byte{byte(n)})
|
||||
emit(w, opcode.PUSHDATA1, []byte{byte(n)})
|
||||
case n < 0x10000:
|
||||
buf := make([]byte, 2)
|
||||
binary.LittleEndian.PutUint16(buf, uint16(n))
|
||||
emit(w, vm.PUSHDATA2, buf)
|
||||
emit(w, opcode.PUSHDATA2, buf)
|
||||
default:
|
||||
buf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(buf, uint32(n))
|
||||
emit(w, vm.PUSHDATA4, buf)
|
||||
emit(w, opcode.PUSHDATA4, buf)
|
||||
if w.Err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -92,16 +92,16 @@ func emitSyscall(w *io.BinWriter, api string) {
|
|||
buf := make([]byte, len(api)+1)
|
||||
buf[0] = byte(len(api))
|
||||
copy(buf[1:], api)
|
||||
emit(w, vm.SYSCALL, buf)
|
||||
emit(w, opcode.SYSCALL, buf)
|
||||
}
|
||||
|
||||
// emitCall emits a call Instruction with label to the given buffer.
|
||||
func emitCall(w *io.BinWriter, instr vm.Instruction, label int16) {
|
||||
func emitCall(w *io.BinWriter, instr opcode.Opcode, label int16) {
|
||||
emitJmp(w, instr, label)
|
||||
}
|
||||
|
||||
// emitJmp emits a jump Instruction along with label to the given buffer.
|
||||
func emitJmp(w *io.BinWriter, instr vm.Instruction, label int16) {
|
||||
func emitJmp(w *io.BinWriter, instr opcode.Opcode, label int16) {
|
||||
if !isInstrJmp(instr) {
|
||||
w.Err = fmt.Errorf("opcode %s is not a jump or call type", instr)
|
||||
return
|
||||
|
@ -111,8 +111,8 @@ func emitJmp(w *io.BinWriter, instr vm.Instruction, label int16) {
|
|||
emit(w, instr, buf)
|
||||
}
|
||||
|
||||
func isInstrJmp(instr vm.Instruction) bool {
|
||||
if instr == vm.JMP || instr == vm.JMPIFNOT || instr == vm.JMPIF || instr == vm.CALL {
|
||||
func isInstrJmp(instr opcode.Opcode) bool {
|
||||
if instr == opcode.JMP || instr == opcode.JMPIFNOT || instr == opcode.JMPIF || instr == opcode.CALL {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
// Context represents the current execution context of the VM.
|
||||
|
@ -42,31 +43,31 @@ func NewContext(b []byte) *Context {
|
|||
// Next returns the next instruction to execute with its parameter if any. After
|
||||
// its invocation the instruction pointer points to the instruction being
|
||||
// returned.
|
||||
func (c *Context) Next() (Instruction, []byte, error) {
|
||||
func (c *Context) Next() (opcode.Opcode, []byte, error) {
|
||||
c.ip = c.nextip
|
||||
if c.ip >= len(c.prog) {
|
||||
return RET, nil, nil
|
||||
return opcode.RET, nil, nil
|
||||
}
|
||||
r := io.NewBinReaderFromBuf(c.prog[c.ip:])
|
||||
|
||||
var instrbyte byte
|
||||
r.ReadLE(&instrbyte)
|
||||
instr := Instruction(instrbyte)
|
||||
instr := opcode.Opcode(instrbyte)
|
||||
c.nextip++
|
||||
|
||||
var numtoread int
|
||||
switch instr {
|
||||
case PUSHDATA1, SYSCALL:
|
||||
case opcode.PUSHDATA1, opcode.SYSCALL:
|
||||
var n byte
|
||||
r.ReadLE(&n)
|
||||
numtoread = int(n)
|
||||
c.nextip++
|
||||
case PUSHDATA2:
|
||||
case opcode.PUSHDATA2:
|
||||
var n uint16
|
||||
r.ReadLE(&n)
|
||||
numtoread = int(n)
|
||||
c.nextip += 2
|
||||
case PUSHDATA4:
|
||||
case opcode.PUSHDATA4:
|
||||
var n uint32
|
||||
r.ReadLE(&n)
|
||||
if n > MaxItemSize {
|
||||
|
@ -74,16 +75,16 @@ func (c *Context) Next() (Instruction, []byte, error) {
|
|||
}
|
||||
numtoread = int(n)
|
||||
c.nextip += 4
|
||||
case JMP, JMPIF, JMPIFNOT, CALL, CALLED, CALLEDT:
|
||||
case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.CALL, opcode.CALLED, opcode.CALLEDT:
|
||||
numtoread = 2
|
||||
case CALLI:
|
||||
case opcode.CALLI:
|
||||
numtoread = 4
|
||||
case APPCALL, TAILCALL:
|
||||
case opcode.APPCALL, opcode.TAILCALL:
|
||||
numtoread = 20
|
||||
case CALLE, CALLET:
|
||||
case opcode.CALLE, opcode.CALLET:
|
||||
numtoread = 22
|
||||
default:
|
||||
if instr >= PUSHBYTES1 && instr <= PUSHBYTES75 {
|
||||
if instr >= opcode.PUSHBYTES1 && instr <= opcode.PUSHBYTES75 {
|
||||
numtoread = int(instr)
|
||||
} else {
|
||||
// No parameters, can just return.
|
||||
|
@ -112,8 +113,8 @@ func (c *Context) LenInstr() int {
|
|||
}
|
||||
|
||||
// CurrInstr returns the current instruction and opcode.
|
||||
func (c *Context) CurrInstr() (int, Instruction) {
|
||||
return c.ip, Instruction(c.prog[c.ip])
|
||||
func (c *Context) CurrInstr() (int, opcode.Opcode) {
|
||||
return c.ip, opcode.Opcode(c.prog[c.ip])
|
||||
}
|
||||
|
||||
// Copy returns an new exact copy of c.
|
||||
|
|
|
@ -2,18 +2,22 @@ package vm
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
func getNumOfThingsFromInstr(instr Instruction, param []byte) (int, bool) {
|
||||
func getNumOfThingsFromInstr(instr opcode.Opcode, param []byte) (int, bool) {
|
||||
var nthings int
|
||||
|
||||
switch instr {
|
||||
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8,
|
||||
PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16:
|
||||
nthings = int(instr-PUSH1) + 1
|
||||
case PUSHBYTES1:
|
||||
case opcode.PUSH1, opcode.PUSH2, opcode.PUSH3, opcode.PUSH4,
|
||||
opcode.PUSH5, opcode.PUSH6, opcode.PUSH7, opcode.PUSH8,
|
||||
opcode.PUSH9, opcode.PUSH10, opcode.PUSH11, opcode.PUSH12,
|
||||
opcode.PUSH13, opcode.PUSH14, opcode.PUSH15, opcode.PUSH16:
|
||||
nthings = int(instr-opcode.PUSH1) + 1
|
||||
case opcode.PUSHBYTES1:
|
||||
nthings = int(param[0])
|
||||
case PUSHBYTES2:
|
||||
case opcode.PUSHBYTES2:
|
||||
nthings = int(binary.LittleEndian.Uint16(param))
|
||||
default:
|
||||
return 0, false
|
||||
|
@ -43,7 +47,7 @@ func IsMultiSigContract(script []byte) bool {
|
|||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if instr != PUSHBYTES33 {
|
||||
if instr != opcode.PUSHBYTES33 {
|
||||
break
|
||||
}
|
||||
nkeys++
|
||||
|
@ -62,11 +66,11 @@ func IsMultiSigContract(script []byte) bool {
|
|||
return false
|
||||
}
|
||||
instr, _, err = ctx.Next()
|
||||
if err != nil || instr != CHECKMULTISIG {
|
||||
if err != nil || instr != opcode.CHECKMULTISIG {
|
||||
return false
|
||||
}
|
||||
instr, _, err = ctx.Next()
|
||||
if err != nil || instr != RET || ctx.ip != len(script) {
|
||||
if err != nil || instr != opcode.RET || ctx.ip != len(script) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
@ -77,15 +81,15 @@ func IsMultiSigContract(script []byte) bool {
|
|||
func IsSignatureContract(script []byte) bool {
|
||||
ctx := NewContext(script)
|
||||
instr, _, err := ctx.Next()
|
||||
if err != nil || instr != PUSHBYTES33 {
|
||||
if err != nil || instr != opcode.PUSHBYTES33 {
|
||||
return false
|
||||
}
|
||||
instr, _, err = ctx.Next()
|
||||
if err != nil || instr != CHECKSIG {
|
||||
if err != nil || instr != opcode.CHECKSIG {
|
||||
return false
|
||||
}
|
||||
instr, _, err = ctx.Next()
|
||||
if err != nil || instr != RET || ctx.ip != len(script) {
|
||||
if err != nil || instr != opcode.RET || ctx.ip != len(script) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -3,225 +3,226 @@ package vm
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIsSignatureContractGood(t *testing.T) {
|
||||
prog := make([]byte, 35)
|
||||
prog[0] = byte(PUSHBYTES33)
|
||||
prog[34] = byte(CHECKSIG)
|
||||
prog[0] = byte(opcode.PUSHBYTES33)
|
||||
prog[34] = byte(opcode.CHECKSIG)
|
||||
assert.Equal(t, true, IsSignatureContract(prog))
|
||||
assert.Equal(t, true, IsStandardContract(prog))
|
||||
}
|
||||
|
||||
func TestIsSignatureContractBadNoCheckSig(t *testing.T) {
|
||||
prog := make([]byte, 34)
|
||||
prog[0] = byte(PUSHBYTES33)
|
||||
prog[0] = byte(opcode.PUSHBYTES33)
|
||||
assert.Equal(t, false, IsSignatureContract(prog))
|
||||
assert.Equal(t, false, IsStandardContract(prog))
|
||||
}
|
||||
|
||||
func TestIsSignatureContractBadNoCheckSig2(t *testing.T) {
|
||||
prog := make([]byte, 35)
|
||||
prog[0] = byte(PUSHBYTES33)
|
||||
prog[34] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSHBYTES33)
|
||||
prog[34] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsSignatureContract(prog))
|
||||
}
|
||||
|
||||
func TestIsSignatureContractBadWrongPush(t *testing.T) {
|
||||
prog := make([]byte, 35)
|
||||
prog[0] = byte(PUSHBYTES32)
|
||||
prog[33] = byte(NOP)
|
||||
prog[34] = byte(CHECKSIG)
|
||||
prog[0] = byte(opcode.PUSHBYTES32)
|
||||
prog[33] = byte(opcode.NOP)
|
||||
prog[34] = byte(opcode.CHECKSIG)
|
||||
assert.Equal(t, false, IsSignatureContract(prog))
|
||||
}
|
||||
|
||||
func TestIsSignatureContractBadWrongInstr(t *testing.T) {
|
||||
prog := make([]byte, 30)
|
||||
prog[0] = byte(PUSHBYTES33)
|
||||
prog[0] = byte(opcode.PUSHBYTES33)
|
||||
assert.Equal(t, false, IsSignatureContract(prog))
|
||||
}
|
||||
|
||||
func TestIsSignatureContractBadExcessiveInstr(t *testing.T) {
|
||||
prog := make([]byte, 36)
|
||||
prog[0] = byte(PUSHBYTES33)
|
||||
prog[34] = byte(CHECKSIG)
|
||||
prog[35] = byte(RET)
|
||||
prog[0] = byte(opcode.PUSHBYTES33)
|
||||
prog[34] = byte(opcode.CHECKSIG)
|
||||
prog[35] = byte(opcode.RET)
|
||||
assert.Equal(t, false, IsSignatureContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractGood(t *testing.T) {
|
||||
prog := make([]byte, 71)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, true, IsMultiSigContract(prog))
|
||||
assert.Equal(t, true, IsStandardContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractGoodPushBytes1(t *testing.T) {
|
||||
prog := make([]byte, 73)
|
||||
prog[0] = byte(PUSHBYTES1)
|
||||
prog[0] = byte(opcode.PUSHBYTES1)
|
||||
prog[1] = 2
|
||||
prog[2] = byte(PUSHBYTES33)
|
||||
prog[36] = byte(PUSHBYTES33)
|
||||
prog[70] = byte(PUSHBYTES1)
|
||||
prog[2] = byte(opcode.PUSHBYTES33)
|
||||
prog[36] = byte(opcode.PUSHBYTES33)
|
||||
prog[70] = byte(opcode.PUSHBYTES1)
|
||||
prog[71] = 2
|
||||
prog[72] = byte(CHECKMULTISIG)
|
||||
prog[72] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, true, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractGoodPushBytes2(t *testing.T) {
|
||||
prog := make([]byte, 75)
|
||||
prog[0] = byte(PUSHBYTES2)
|
||||
prog[0] = byte(opcode.PUSHBYTES2)
|
||||
prog[1] = 2
|
||||
prog[3] = byte(PUSHBYTES33)
|
||||
prog[37] = byte(PUSHBYTES33)
|
||||
prog[71] = byte(PUSHBYTES2)
|
||||
prog[3] = byte(opcode.PUSHBYTES33)
|
||||
prog[37] = byte(opcode.PUSHBYTES33)
|
||||
prog[71] = byte(opcode.PUSHBYTES2)
|
||||
prog[72] = 2
|
||||
prog[74] = byte(CHECKMULTISIG)
|
||||
prog[74] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, true, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadNSigs1(t *testing.T) {
|
||||
prog := make([]byte, 71)
|
||||
prog[0] = byte(PUSH0)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH0)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
assert.Equal(t, false, IsStandardContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadNSigs2(t *testing.T) {
|
||||
prog := make([]byte, 73)
|
||||
prog[0] = byte(PUSHBYTES2)
|
||||
prog[0] = byte(opcode.PUSHBYTES2)
|
||||
prog[1] = 0xff
|
||||
prog[2] = 0xff
|
||||
prog[3] = byte(PUSHBYTES33)
|
||||
prog[37] = byte(PUSHBYTES33)
|
||||
prog[71] = byte(PUSH2)
|
||||
prog[72] = byte(CHECKMULTISIG)
|
||||
prog[3] = byte(opcode.PUSHBYTES33)
|
||||
prog[37] = byte(opcode.PUSHBYTES33)
|
||||
prog[71] = byte(opcode.PUSH2)
|
||||
prog[72] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadNSigs3(t *testing.T) {
|
||||
prog := make([]byte, 71)
|
||||
prog[0] = byte(PUSH5)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH5)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadExcessiveNOP1(t *testing.T) {
|
||||
prog := make([]byte, 72)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(NOP)
|
||||
prog[2] = byte(PUSHBYTES33)
|
||||
prog[36] = byte(PUSHBYTES33)
|
||||
prog[70] = byte(PUSH2)
|
||||
prog[71] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.NOP)
|
||||
prog[2] = byte(opcode.PUSHBYTES33)
|
||||
prog[36] = byte(opcode.PUSHBYTES33)
|
||||
prog[70] = byte(opcode.PUSH2)
|
||||
prog[71] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadExcessiveNOP2(t *testing.T) {
|
||||
prog := make([]byte, 72)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(NOP)
|
||||
prog[36] = byte(PUSHBYTES33)
|
||||
prog[70] = byte(PUSH2)
|
||||
prog[71] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.NOP)
|
||||
prog[36] = byte(opcode.PUSHBYTES33)
|
||||
prog[70] = byte(opcode.PUSH2)
|
||||
prog[71] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadExcessiveNOP3(t *testing.T) {
|
||||
prog := make([]byte, 72)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(NOP)
|
||||
prog[70] = byte(PUSH2)
|
||||
prog[71] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.NOP)
|
||||
prog[70] = byte(opcode.PUSH2)
|
||||
prog[71] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadExcessiveNOP4(t *testing.T) {
|
||||
prog := make([]byte, 72)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(NOP)
|
||||
prog[71] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.NOP)
|
||||
prog[71] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadExcessiveNOP5(t *testing.T) {
|
||||
prog := make([]byte, 72)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(CHECKMULTISIG)
|
||||
prog[71] = byte(NOP)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.CHECKMULTISIG)
|
||||
prog[71] = byte(opcode.NOP)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadNKeys1(t *testing.T) {
|
||||
prog := make([]byte, 71)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH3)
|
||||
prog[70] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH3)
|
||||
prog[70] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadNKeys2(t *testing.T) {
|
||||
prog := make([]byte, 1)
|
||||
prog[0] = byte(PUSH10)
|
||||
prog[0] = byte(opcode.PUSH10)
|
||||
key := make([]byte, 33)
|
||||
var asize = uint16(MaxArraySize + 1)
|
||||
for i := 0; i < int(asize); i++ {
|
||||
prog = append(prog, byte(PUSHBYTES33))
|
||||
prog = append(prog, byte(opcode.PUSHBYTES33))
|
||||
prog = append(prog, key...)
|
||||
}
|
||||
prog = append(prog, byte(PUSHBYTES2), byte(asize&0xff), byte((asize<<8)&0xff), byte(CHECKMULTISIG))
|
||||
prog = append(prog, byte(opcode.PUSHBYTES2), byte(asize&0xff), byte((asize<<8)&0xff), byte(opcode.CHECKMULTISIG))
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadRead1(t *testing.T) {
|
||||
prog := make([]byte, 71)
|
||||
prog[0] = byte(PUSHBYTES75)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSHBYTES75)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadRead2(t *testing.T) {
|
||||
prog := make([]byte, 71)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES75)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(CHECKMULTISIG)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES75)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.CHECKMULTISIG)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
||||
func TestIsMultiSigContractBadRead3(t *testing.T) {
|
||||
prog := make([]byte, 71)
|
||||
prog[0] = byte(PUSH2)
|
||||
prog[1] = byte(PUSHBYTES33)
|
||||
prog[35] = byte(PUSHBYTES33)
|
||||
prog[69] = byte(PUSH2)
|
||||
prog[70] = byte(PUSHBYTES1)
|
||||
prog[0] = byte(opcode.PUSH2)
|
||||
prog[1] = byte(opcode.PUSHBYTES33)
|
||||
prog[35] = byte(opcode.PUSHBYTES33)
|
||||
prog[69] = byte(opcode.PUSH2)
|
||||
prog[70] = byte(opcode.PUSHBYTES1)
|
||||
assert.Equal(t, false, IsMultiSigContract(prog))
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@ import (
|
|||
"math/big"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
// Emit a VM Instruction with data to the given buffer.
|
||||
func Emit(w *bytes.Buffer, op Instruction, b []byte) error {
|
||||
func Emit(w *bytes.Buffer, op opcode.Opcode, b []byte) error {
|
||||
if err := w.WriteByte(byte(op)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -21,28 +22,28 @@ func Emit(w *bytes.Buffer, op Instruction, b []byte) error {
|
|||
}
|
||||
|
||||
// EmitOpcode emits a single VM Instruction the given buffer.
|
||||
func EmitOpcode(w io.ByteWriter, op Instruction) error {
|
||||
func EmitOpcode(w io.ByteWriter, op opcode.Opcode) error {
|
||||
return w.WriteByte(byte(op))
|
||||
}
|
||||
|
||||
// EmitBool emits a bool type the given buffer.
|
||||
func EmitBool(w io.ByteWriter, ok bool) error {
|
||||
if ok {
|
||||
return EmitOpcode(w, PUSHT)
|
||||
return EmitOpcode(w, opcode.PUSHT)
|
||||
}
|
||||
return EmitOpcode(w, PUSHF)
|
||||
return EmitOpcode(w, opcode.PUSHF)
|
||||
}
|
||||
|
||||
// EmitInt emits a int type to the given buffer.
|
||||
func EmitInt(w *bytes.Buffer, i int64) error {
|
||||
if i == -1 {
|
||||
return EmitOpcode(w, PUSHM1)
|
||||
return EmitOpcode(w, opcode.PUSHM1)
|
||||
}
|
||||
if i == 0 {
|
||||
return EmitOpcode(w, PUSHF)
|
||||
return EmitOpcode(w, opcode.PUSHF)
|
||||
}
|
||||
if i > 0 && i < 16 {
|
||||
val := Instruction(int(PUSH1) - 1 + int(i))
|
||||
val := opcode.Opcode(int(opcode.PUSH1) - 1 + int(i))
|
||||
return EmitOpcode(w, val)
|
||||
}
|
||||
|
||||
|
@ -63,18 +64,18 @@ func EmitBytes(w *bytes.Buffer, b []byte) error {
|
|||
n = len(b)
|
||||
)
|
||||
|
||||
if n <= int(PUSHBYTES75) {
|
||||
return Emit(w, Instruction(n), b)
|
||||
if n <= int(opcode.PUSHBYTES75) {
|
||||
return Emit(w, opcode.Opcode(n), b)
|
||||
} else if n < 0x100 {
|
||||
err = Emit(w, PUSHDATA1, []byte{byte(n)})
|
||||
err = Emit(w, opcode.PUSHDATA1, []byte{byte(n)})
|
||||
} else if n < 0x10000 {
|
||||
buf := make([]byte, 2)
|
||||
binary.LittleEndian.PutUint16(buf, uint16(n))
|
||||
err = Emit(w, PUSHDATA2, buf)
|
||||
err = Emit(w, opcode.PUSHDATA2, buf)
|
||||
} else {
|
||||
buf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(buf, uint32(n))
|
||||
err = Emit(w, PUSHDATA4, buf)
|
||||
err = Emit(w, opcode.PUSHDATA4, buf)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -92,16 +93,16 @@ func EmitSyscall(w *bytes.Buffer, api string) error {
|
|||
buf := make([]byte, len(api)+1)
|
||||
buf[0] = byte(len(api))
|
||||
copy(buf[1:], api)
|
||||
return Emit(w, SYSCALL, buf)
|
||||
return Emit(w, opcode.SYSCALL, buf)
|
||||
}
|
||||
|
||||
// EmitCall emits a call Instruction with label to the given buffer.
|
||||
func EmitCall(w *bytes.Buffer, op Instruction, label int16) error {
|
||||
func EmitCall(w *bytes.Buffer, op opcode.Opcode, label int16) error {
|
||||
return EmitJmp(w, op, label)
|
||||
}
|
||||
|
||||
// EmitJmp emits a jump Instruction along with label to the given buffer.
|
||||
func EmitJmp(w *bytes.Buffer, op Instruction, label int16) error {
|
||||
func EmitJmp(w *bytes.Buffer, op opcode.Opcode, label int16) error {
|
||||
if !isInstructionJmp(op) {
|
||||
return fmt.Errorf("opcode %s is not a jump or call type", op.String())
|
||||
}
|
||||
|
@ -113,9 +114,9 @@ func EmitJmp(w *bytes.Buffer, op Instruction, label int16) error {
|
|||
// EmitAppCall emits an appcall, if tailCall is true, tailCall opcode will be
|
||||
// emitted instead.
|
||||
func EmitAppCall(w *bytes.Buffer, scriptHash util.Uint160, tailCall bool) error {
|
||||
op := APPCALL
|
||||
op := opcode.APPCALL
|
||||
if tailCall {
|
||||
op = TAILCALL
|
||||
op = opcode.TAILCALL
|
||||
}
|
||||
return Emit(w, op, scriptHash.Bytes())
|
||||
}
|
||||
|
@ -142,8 +143,8 @@ func EmitAppCallWithOperation(w *bytes.Buffer, scriptHash util.Uint160, operatio
|
|||
return EmitAppCall(w, scriptHash, false)
|
||||
}
|
||||
|
||||
func isInstructionJmp(op Instruction) bool {
|
||||
if op == JMP || op == JMPIFNOT || op == JMPIF || op == CALL {
|
||||
func isInstructionJmp(op opcode.Opcode) bool {
|
||||
if op == opcode.JMP || op == opcode.JMPIFNOT || op == opcode.JMPIF || op == opcode.CALL {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -5,13 +5,14 @@ import (
|
|||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEmitInt(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
EmitInt(buf, 10)
|
||||
assert.Equal(t, Instruction(buf.Bytes()[0]), PUSH10)
|
||||
assert.Equal(t, opcode.Opcode(buf.Bytes()[0]), opcode.PUSH10)
|
||||
buf.Reset()
|
||||
EmitInt(buf, 100)
|
||||
assert.Equal(t, buf.Bytes()[0], uint8(1))
|
||||
|
@ -26,8 +27,8 @@ func TestEmitBool(t *testing.T) {
|
|||
buf := new(bytes.Buffer)
|
||||
EmitBool(buf, true)
|
||||
EmitBool(buf, false)
|
||||
assert.Equal(t, Instruction(buf.Bytes()[0]), PUSH1)
|
||||
assert.Equal(t, Instruction(buf.Bytes()[1]), PUSH0)
|
||||
assert.Equal(t, opcode.Opcode(buf.Bytes()[0]), opcode.PUSH1)
|
||||
assert.Equal(t, opcode.Opcode(buf.Bytes()[1]), opcode.PUSH0)
|
||||
}
|
||||
|
||||
func TestEmitString(t *testing.T) {
|
||||
|
@ -48,7 +49,7 @@ func TestEmitSyscall(t *testing.T) {
|
|||
buf := new(bytes.Buffer)
|
||||
for _, syscall := range syscalls {
|
||||
EmitSyscall(buf, syscall)
|
||||
assert.Equal(t, Instruction(buf.Bytes()[0]), SYSCALL)
|
||||
assert.Equal(t, opcode.Opcode(buf.Bytes()[0]), opcode.SYSCALL)
|
||||
assert.Equal(t, buf.Bytes()[1], uint8(len(syscall)))
|
||||
assert.Equal(t, buf.Bytes()[2:], []byte(syscall))
|
||||
buf.Reset()
|
||||
|
@ -57,8 +58,8 @@ func TestEmitSyscall(t *testing.T) {
|
|||
|
||||
func TestEmitCall(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
EmitCall(buf, JMP, 100)
|
||||
assert.Equal(t, Instruction(buf.Bytes()[0]), JMP)
|
||||
EmitCall(buf, opcode.JMP, 100)
|
||||
assert.Equal(t, opcode.Opcode(buf.Bytes()[0]), opcode.JMP)
|
||||
label := binary.LittleEndian.Uint16(buf.Bytes()[1:3])
|
||||
assert.Equal(t, label, uint16(100))
|
||||
}
|
||||
|
|
|
@ -1,393 +0,0 @@
|
|||
// Code generated by "stringer -type=Instruction"; DO NOT EDIT.
|
||||
|
||||
package vm
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[PUSH0-0]
|
||||
_ = x[PUSHF-0]
|
||||
_ = x[PUSHBYTES1-1]
|
||||
_ = x[PUSHBYTES2-2]
|
||||
_ = x[PUSHBYTES3-3]
|
||||
_ = x[PUSHBYTES4-4]
|
||||
_ = x[PUSHBYTES5-5]
|
||||
_ = x[PUSHBYTES6-6]
|
||||
_ = x[PUSHBYTES7-7]
|
||||
_ = x[PUSHBYTES8-8]
|
||||
_ = x[PUSHBYTES9-9]
|
||||
_ = x[PUSHBYTES10-10]
|
||||
_ = x[PUSHBYTES11-11]
|
||||
_ = x[PUSHBYTES12-12]
|
||||
_ = x[PUSHBYTES13-13]
|
||||
_ = x[PUSHBYTES14-14]
|
||||
_ = x[PUSHBYTES15-15]
|
||||
_ = x[PUSHBYTES16-16]
|
||||
_ = x[PUSHBYTES17-17]
|
||||
_ = x[PUSHBYTES18-18]
|
||||
_ = x[PUSHBYTES19-19]
|
||||
_ = x[PUSHBYTES20-20]
|
||||
_ = x[PUSHBYTES21-21]
|
||||
_ = x[PUSHBYTES22-22]
|
||||
_ = x[PUSHBYTES23-23]
|
||||
_ = x[PUSHBYTES24-24]
|
||||
_ = x[PUSHBYTES25-25]
|
||||
_ = x[PUSHBYTES26-26]
|
||||
_ = x[PUSHBYTES27-27]
|
||||
_ = x[PUSHBYTES28-28]
|
||||
_ = x[PUSHBYTES29-29]
|
||||
_ = x[PUSHBYTES30-30]
|
||||
_ = x[PUSHBYTES31-31]
|
||||
_ = x[PUSHBYTES32-32]
|
||||
_ = x[PUSHBYTES33-33]
|
||||
_ = x[PUSHBYTES34-34]
|
||||
_ = x[PUSHBYTES35-35]
|
||||
_ = x[PUSHBYTES36-36]
|
||||
_ = x[PUSHBYTES37-37]
|
||||
_ = x[PUSHBYTES38-38]
|
||||
_ = x[PUSHBYTES39-39]
|
||||
_ = x[PUSHBYTES40-40]
|
||||
_ = x[PUSHBYTES41-41]
|
||||
_ = x[PUSHBYTES42-42]
|
||||
_ = x[PUSHBYTES43-43]
|
||||
_ = x[PUSHBYTES44-44]
|
||||
_ = x[PUSHBYTES45-45]
|
||||
_ = x[PUSHBYTES46-46]
|
||||
_ = x[PUSHBYTES47-47]
|
||||
_ = x[PUSHBYTES48-48]
|
||||
_ = x[PUSHBYTES49-49]
|
||||
_ = x[PUSHBYTES50-50]
|
||||
_ = x[PUSHBYTES51-51]
|
||||
_ = x[PUSHBYTES52-52]
|
||||
_ = x[PUSHBYTES53-53]
|
||||
_ = x[PUSHBYTES54-54]
|
||||
_ = x[PUSHBYTES55-55]
|
||||
_ = x[PUSHBYTES56-56]
|
||||
_ = x[PUSHBYTES57-57]
|
||||
_ = x[PUSHBYTES58-58]
|
||||
_ = x[PUSHBYTES59-59]
|
||||
_ = x[PUSHBYTES60-60]
|
||||
_ = x[PUSHBYTES61-61]
|
||||
_ = x[PUSHBYTES62-62]
|
||||
_ = x[PUSHBYTES63-63]
|
||||
_ = x[PUSHBYTES64-64]
|
||||
_ = x[PUSHBYTES65-65]
|
||||
_ = x[PUSHBYTES66-66]
|
||||
_ = x[PUSHBYTES67-67]
|
||||
_ = x[PUSHBYTES68-68]
|
||||
_ = x[PUSHBYTES69-69]
|
||||
_ = x[PUSHBYTES70-70]
|
||||
_ = x[PUSHBYTES71-71]
|
||||
_ = x[PUSHBYTES72-72]
|
||||
_ = x[PUSHBYTES73-73]
|
||||
_ = x[PUSHBYTES74-74]
|
||||
_ = x[PUSHBYTES75-75]
|
||||
_ = x[PUSHDATA1-76]
|
||||
_ = x[PUSHDATA2-77]
|
||||
_ = x[PUSHDATA4-78]
|
||||
_ = x[PUSHM1-79]
|
||||
_ = x[PUSH1-81]
|
||||
_ = x[PUSHT-81]
|
||||
_ = x[PUSH2-82]
|
||||
_ = x[PUSH3-83]
|
||||
_ = x[PUSH4-84]
|
||||
_ = x[PUSH5-85]
|
||||
_ = x[PUSH6-86]
|
||||
_ = x[PUSH7-87]
|
||||
_ = x[PUSH8-88]
|
||||
_ = x[PUSH9-89]
|
||||
_ = x[PUSH10-90]
|
||||
_ = x[PUSH11-91]
|
||||
_ = x[PUSH12-92]
|
||||
_ = x[PUSH13-93]
|
||||
_ = x[PUSH14-94]
|
||||
_ = x[PUSH15-95]
|
||||
_ = x[PUSH16-96]
|
||||
_ = x[NOP-97]
|
||||
_ = x[JMP-98]
|
||||
_ = x[JMPIF-99]
|
||||
_ = x[JMPIFNOT-100]
|
||||
_ = x[CALL-101]
|
||||
_ = x[RET-102]
|
||||
_ = x[APPCALL-103]
|
||||
_ = x[SYSCALL-104]
|
||||
_ = x[TAILCALL-105]
|
||||
_ = x[DUPFROMALTSTACK-106]
|
||||
_ = x[TOALTSTACK-107]
|
||||
_ = x[FROMALTSTACK-108]
|
||||
_ = x[XDROP-109]
|
||||
_ = x[XSWAP-114]
|
||||
_ = x[XTUCK-115]
|
||||
_ = x[DEPTH-116]
|
||||
_ = x[DROP-117]
|
||||
_ = x[DUP-118]
|
||||
_ = x[NIP-119]
|
||||
_ = x[OVER-120]
|
||||
_ = x[PICK-121]
|
||||
_ = x[ROLL-122]
|
||||
_ = x[ROT-123]
|
||||
_ = x[SWAP-124]
|
||||
_ = x[TUCK-125]
|
||||
_ = x[CAT-126]
|
||||
_ = x[SUBSTR-127]
|
||||
_ = x[LEFT-128]
|
||||
_ = x[RIGHT-129]
|
||||
_ = x[SIZE-130]
|
||||
_ = x[INVERT-131]
|
||||
_ = x[AND-132]
|
||||
_ = x[OR-133]
|
||||
_ = x[XOR-134]
|
||||
_ = x[EQUAL-135]
|
||||
_ = x[INC-139]
|
||||
_ = x[DEC-140]
|
||||
_ = x[SIGN-141]
|
||||
_ = x[NEGATE-143]
|
||||
_ = x[ABS-144]
|
||||
_ = x[NOT-145]
|
||||
_ = x[NZ-146]
|
||||
_ = x[ADD-147]
|
||||
_ = x[SUB-148]
|
||||
_ = x[MUL-149]
|
||||
_ = x[DIV-150]
|
||||
_ = x[MOD-151]
|
||||
_ = x[SHL-152]
|
||||
_ = x[SHR-153]
|
||||
_ = x[BOOLAND-154]
|
||||
_ = x[BOOLOR-155]
|
||||
_ = x[NUMEQUAL-156]
|
||||
_ = x[NUMNOTEQUAL-158]
|
||||
_ = x[LT-159]
|
||||
_ = x[GT-160]
|
||||
_ = x[LTE-161]
|
||||
_ = x[GTE-162]
|
||||
_ = x[MIN-163]
|
||||
_ = x[MAX-164]
|
||||
_ = x[WITHIN-165]
|
||||
_ = x[SHA1-167]
|
||||
_ = x[SHA256-168]
|
||||
_ = x[HASH160-169]
|
||||
_ = x[HASH256-170]
|
||||
_ = x[CHECKSIG-172]
|
||||
_ = x[VERIFY-173]
|
||||
_ = x[CHECKMULTISIG-174]
|
||||
_ = x[ARRAYSIZE-192]
|
||||
_ = x[PACK-193]
|
||||
_ = x[UNPACK-194]
|
||||
_ = x[PICKITEM-195]
|
||||
_ = x[SETITEM-196]
|
||||
_ = x[NEWARRAY-197]
|
||||
_ = x[NEWSTRUCT-198]
|
||||
_ = x[NEWMAP-199]
|
||||
_ = x[APPEND-200]
|
||||
_ = x[REVERSE-201]
|
||||
_ = x[REMOVE-202]
|
||||
_ = x[HASKEY-203]
|
||||
_ = x[KEYS-204]
|
||||
_ = x[VALUES-205]
|
||||
_ = x[CALLI-224]
|
||||
_ = x[CALLE-225]
|
||||
_ = x[CALLED-226]
|
||||
_ = x[CALLET-227]
|
||||
_ = x[CALLEDT-228]
|
||||
_ = x[THROW-240]
|
||||
_ = x[THROWIFNOT-241]
|
||||
}
|
||||
|
||||
const _Instruction_name = "PUSH0PUSHBYTES1PUSHBYTES2PUSHBYTES3PUSHBYTES4PUSHBYTES5PUSHBYTES6PUSHBYTES7PUSHBYTES8PUSHBYTES9PUSHBYTES10PUSHBYTES11PUSHBYTES12PUSHBYTES13PUSHBYTES14PUSHBYTES15PUSHBYTES16PUSHBYTES17PUSHBYTES18PUSHBYTES19PUSHBYTES20PUSHBYTES21PUSHBYTES22PUSHBYTES23PUSHBYTES24PUSHBYTES25PUSHBYTES26PUSHBYTES27PUSHBYTES28PUSHBYTES29PUSHBYTES30PUSHBYTES31PUSHBYTES32PUSHBYTES33PUSHBYTES34PUSHBYTES35PUSHBYTES36PUSHBYTES37PUSHBYTES38PUSHBYTES39PUSHBYTES40PUSHBYTES41PUSHBYTES42PUSHBYTES43PUSHBYTES44PUSHBYTES45PUSHBYTES46PUSHBYTES47PUSHBYTES48PUSHBYTES49PUSHBYTES50PUSHBYTES51PUSHBYTES52PUSHBYTES53PUSHBYTES54PUSHBYTES55PUSHBYTES56PUSHBYTES57PUSHBYTES58PUSHBYTES59PUSHBYTES60PUSHBYTES61PUSHBYTES62PUSHBYTES63PUSHBYTES64PUSHBYTES65PUSHBYTES66PUSHBYTES67PUSHBYTES68PUSHBYTES69PUSHBYTES70PUSHBYTES71PUSHBYTES72PUSHBYTES73PUSHBYTES74PUSHBYTES75PUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPIFJMPIFNOTCALLRETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTSIZEINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGARRAYSIZEPACKUNPACKPICKITEMSETITEMNEWARRAYNEWSTRUCTNEWMAPAPPENDREVERSEREMOVEHASKEYKEYSVALUESCALLICALLECALLEDCALLETCALLEDTTHROWTHROWIFNOT"
|
||||
|
||||
var _Instruction_map = map[Instruction]string{
|
||||
0: _Instruction_name[0:5],
|
||||
1: _Instruction_name[5:15],
|
||||
2: _Instruction_name[15:25],
|
||||
3: _Instruction_name[25:35],
|
||||
4: _Instruction_name[35:45],
|
||||
5: _Instruction_name[45:55],
|
||||
6: _Instruction_name[55:65],
|
||||
7: _Instruction_name[65:75],
|
||||
8: _Instruction_name[75:85],
|
||||
9: _Instruction_name[85:95],
|
||||
10: _Instruction_name[95:106],
|
||||
11: _Instruction_name[106:117],
|
||||
12: _Instruction_name[117:128],
|
||||
13: _Instruction_name[128:139],
|
||||
14: _Instruction_name[139:150],
|
||||
15: _Instruction_name[150:161],
|
||||
16: _Instruction_name[161:172],
|
||||
17: _Instruction_name[172:183],
|
||||
18: _Instruction_name[183:194],
|
||||
19: _Instruction_name[194:205],
|
||||
20: _Instruction_name[205:216],
|
||||
21: _Instruction_name[216:227],
|
||||
22: _Instruction_name[227:238],
|
||||
23: _Instruction_name[238:249],
|
||||
24: _Instruction_name[249:260],
|
||||
25: _Instruction_name[260:271],
|
||||
26: _Instruction_name[271:282],
|
||||
27: _Instruction_name[282:293],
|
||||
28: _Instruction_name[293:304],
|
||||
29: _Instruction_name[304:315],
|
||||
30: _Instruction_name[315:326],
|
||||
31: _Instruction_name[326:337],
|
||||
32: _Instruction_name[337:348],
|
||||
33: _Instruction_name[348:359],
|
||||
34: _Instruction_name[359:370],
|
||||
35: _Instruction_name[370:381],
|
||||
36: _Instruction_name[381:392],
|
||||
37: _Instruction_name[392:403],
|
||||
38: _Instruction_name[403:414],
|
||||
39: _Instruction_name[414:425],
|
||||
40: _Instruction_name[425:436],
|
||||
41: _Instruction_name[436:447],
|
||||
42: _Instruction_name[447:458],
|
||||
43: _Instruction_name[458:469],
|
||||
44: _Instruction_name[469:480],
|
||||
45: _Instruction_name[480:491],
|
||||
46: _Instruction_name[491:502],
|
||||
47: _Instruction_name[502:513],
|
||||
48: _Instruction_name[513:524],
|
||||
49: _Instruction_name[524:535],
|
||||
50: _Instruction_name[535:546],
|
||||
51: _Instruction_name[546:557],
|
||||
52: _Instruction_name[557:568],
|
||||
53: _Instruction_name[568:579],
|
||||
54: _Instruction_name[579:590],
|
||||
55: _Instruction_name[590:601],
|
||||
56: _Instruction_name[601:612],
|
||||
57: _Instruction_name[612:623],
|
||||
58: _Instruction_name[623:634],
|
||||
59: _Instruction_name[634:645],
|
||||
60: _Instruction_name[645:656],
|
||||
61: _Instruction_name[656:667],
|
||||
62: _Instruction_name[667:678],
|
||||
63: _Instruction_name[678:689],
|
||||
64: _Instruction_name[689:700],
|
||||
65: _Instruction_name[700:711],
|
||||
66: _Instruction_name[711:722],
|
||||
67: _Instruction_name[722:733],
|
||||
68: _Instruction_name[733:744],
|
||||
69: _Instruction_name[744:755],
|
||||
70: _Instruction_name[755:766],
|
||||
71: _Instruction_name[766:777],
|
||||
72: _Instruction_name[777:788],
|
||||
73: _Instruction_name[788:799],
|
||||
74: _Instruction_name[799:810],
|
||||
75: _Instruction_name[810:821],
|
||||
76: _Instruction_name[821:830],
|
||||
77: _Instruction_name[830:839],
|
||||
78: _Instruction_name[839:848],
|
||||
79: _Instruction_name[848:854],
|
||||
81: _Instruction_name[854:859],
|
||||
82: _Instruction_name[859:864],
|
||||
83: _Instruction_name[864:869],
|
||||
84: _Instruction_name[869:874],
|
||||
85: _Instruction_name[874:879],
|
||||
86: _Instruction_name[879:884],
|
||||
87: _Instruction_name[884:889],
|
||||
88: _Instruction_name[889:894],
|
||||
89: _Instruction_name[894:899],
|
||||
90: _Instruction_name[899:905],
|
||||
91: _Instruction_name[905:911],
|
||||
92: _Instruction_name[911:917],
|
||||
93: _Instruction_name[917:923],
|
||||
94: _Instruction_name[923:929],
|
||||
95: _Instruction_name[929:935],
|
||||
96: _Instruction_name[935:941],
|
||||
97: _Instruction_name[941:944],
|
||||
98: _Instruction_name[944:947],
|
||||
99: _Instruction_name[947:952],
|
||||
100: _Instruction_name[952:960],
|
||||
101: _Instruction_name[960:964],
|
||||
102: _Instruction_name[964:967],
|
||||
103: _Instruction_name[967:974],
|
||||
104: _Instruction_name[974:981],
|
||||
105: _Instruction_name[981:989],
|
||||
106: _Instruction_name[989:1004],
|
||||
107: _Instruction_name[1004:1014],
|
||||
108: _Instruction_name[1014:1026],
|
||||
109: _Instruction_name[1026:1031],
|
||||
114: _Instruction_name[1031:1036],
|
||||
115: _Instruction_name[1036:1041],
|
||||
116: _Instruction_name[1041:1046],
|
||||
117: _Instruction_name[1046:1050],
|
||||
118: _Instruction_name[1050:1053],
|
||||
119: _Instruction_name[1053:1056],
|
||||
120: _Instruction_name[1056:1060],
|
||||
121: _Instruction_name[1060:1064],
|
||||
122: _Instruction_name[1064:1068],
|
||||
123: _Instruction_name[1068:1071],
|
||||
124: _Instruction_name[1071:1075],
|
||||
125: _Instruction_name[1075:1079],
|
||||
126: _Instruction_name[1079:1082],
|
||||
127: _Instruction_name[1082:1088],
|
||||
128: _Instruction_name[1088:1092],
|
||||
129: _Instruction_name[1092:1097],
|
||||
130: _Instruction_name[1097:1101],
|
||||
131: _Instruction_name[1101:1107],
|
||||
132: _Instruction_name[1107:1110],
|
||||
133: _Instruction_name[1110:1112],
|
||||
134: _Instruction_name[1112:1115],
|
||||
135: _Instruction_name[1115:1120],
|
||||
139: _Instruction_name[1120:1123],
|
||||
140: _Instruction_name[1123:1126],
|
||||
141: _Instruction_name[1126:1130],
|
||||
143: _Instruction_name[1130:1136],
|
||||
144: _Instruction_name[1136:1139],
|
||||
145: _Instruction_name[1139:1142],
|
||||
146: _Instruction_name[1142:1144],
|
||||
147: _Instruction_name[1144:1147],
|
||||
148: _Instruction_name[1147:1150],
|
||||
149: _Instruction_name[1150:1153],
|
||||
150: _Instruction_name[1153:1156],
|
||||
151: _Instruction_name[1156:1159],
|
||||
152: _Instruction_name[1159:1162],
|
||||
153: _Instruction_name[1162:1165],
|
||||
154: _Instruction_name[1165:1172],
|
||||
155: _Instruction_name[1172:1178],
|
||||
156: _Instruction_name[1178:1186],
|
||||
158: _Instruction_name[1186:1197],
|
||||
159: _Instruction_name[1197:1199],
|
||||
160: _Instruction_name[1199:1201],
|
||||
161: _Instruction_name[1201:1204],
|
||||
162: _Instruction_name[1204:1207],
|
||||
163: _Instruction_name[1207:1210],
|
||||
164: _Instruction_name[1210:1213],
|
||||
165: _Instruction_name[1213:1219],
|
||||
167: _Instruction_name[1219:1223],
|
||||
168: _Instruction_name[1223:1229],
|
||||
169: _Instruction_name[1229:1236],
|
||||
170: _Instruction_name[1236:1243],
|
||||
172: _Instruction_name[1243:1251],
|
||||
173: _Instruction_name[1251:1257],
|
||||
174: _Instruction_name[1257:1270],
|
||||
192: _Instruction_name[1270:1279],
|
||||
193: _Instruction_name[1279:1283],
|
||||
194: _Instruction_name[1283:1289],
|
||||
195: _Instruction_name[1289:1297],
|
||||
196: _Instruction_name[1297:1304],
|
||||
197: _Instruction_name[1304:1312],
|
||||
198: _Instruction_name[1312:1321],
|
||||
199: _Instruction_name[1321:1327],
|
||||
200: _Instruction_name[1327:1333],
|
||||
201: _Instruction_name[1333:1340],
|
||||
202: _Instruction_name[1340:1346],
|
||||
203: _Instruction_name[1346:1352],
|
||||
204: _Instruction_name[1352:1356],
|
||||
205: _Instruction_name[1356:1362],
|
||||
224: _Instruction_name[1362:1367],
|
||||
225: _Instruction_name[1367:1372],
|
||||
226: _Instruction_name[1372:1378],
|
||||
227: _Instruction_name[1378:1384],
|
||||
228: _Instruction_name[1384:1391],
|
||||
240: _Instruction_name[1391:1396],
|
||||
241: _Instruction_name[1396:1406],
|
||||
}
|
||||
|
||||
func (i Instruction) String() string {
|
||||
if str, ok := _Instruction_map[i]; ok {
|
||||
return str
|
||||
}
|
||||
return "Instruction(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
|
@ -1,215 +0,0 @@
|
|||
package vm
|
||||
|
||||
//go:generate stringer -type=Instruction
|
||||
|
||||
// Instruction represents an single operation for the NEO virtual machine.
|
||||
type Instruction byte
|
||||
|
||||
// Viable list of supported instruction constants.
|
||||
const (
|
||||
// Constants
|
||||
PUSH0 Instruction = 0x00
|
||||
PUSHF Instruction = PUSH0
|
||||
PUSHBYTES1 Instruction = 0x01
|
||||
PUSHBYTES2 Instruction = 0x02
|
||||
PUSHBYTES3 Instruction = 0x03
|
||||
PUSHBYTES4 Instruction = 0x04
|
||||
PUSHBYTES5 Instruction = 0x05
|
||||
PUSHBYTES6 Instruction = 0x06
|
||||
PUSHBYTES7 Instruction = 0x07
|
||||
PUSHBYTES8 Instruction = 0x08
|
||||
PUSHBYTES9 Instruction = 0x09
|
||||
PUSHBYTES10 Instruction = 0x0A
|
||||
PUSHBYTES11 Instruction = 0x0B
|
||||
PUSHBYTES12 Instruction = 0x0C
|
||||
PUSHBYTES13 Instruction = 0x0D
|
||||
PUSHBYTES14 Instruction = 0x0E
|
||||
PUSHBYTES15 Instruction = 0x0F
|
||||
PUSHBYTES16 Instruction = 0x10
|
||||
PUSHBYTES17 Instruction = 0x11
|
||||
PUSHBYTES18 Instruction = 0x12
|
||||
PUSHBYTES19 Instruction = 0x13
|
||||
PUSHBYTES20 Instruction = 0x14
|
||||
PUSHBYTES21 Instruction = 0x15
|
||||
PUSHBYTES22 Instruction = 0x16
|
||||
PUSHBYTES23 Instruction = 0x17
|
||||
PUSHBYTES24 Instruction = 0x18
|
||||
PUSHBYTES25 Instruction = 0x19
|
||||
PUSHBYTES26 Instruction = 0x1A
|
||||
PUSHBYTES27 Instruction = 0x1B
|
||||
PUSHBYTES28 Instruction = 0x1C
|
||||
PUSHBYTES29 Instruction = 0x1D
|
||||
PUSHBYTES30 Instruction = 0x1E
|
||||
PUSHBYTES31 Instruction = 0x1F
|
||||
PUSHBYTES32 Instruction = 0x20
|
||||
PUSHBYTES33 Instruction = 0x21
|
||||
PUSHBYTES34 Instruction = 0x22
|
||||
PUSHBYTES35 Instruction = 0x23
|
||||
PUSHBYTES36 Instruction = 0x24
|
||||
PUSHBYTES37 Instruction = 0x25
|
||||
PUSHBYTES38 Instruction = 0x26
|
||||
PUSHBYTES39 Instruction = 0x27
|
||||
PUSHBYTES40 Instruction = 0x28
|
||||
PUSHBYTES41 Instruction = 0x29
|
||||
PUSHBYTES42 Instruction = 0x2A
|
||||
PUSHBYTES43 Instruction = 0x2B
|
||||
PUSHBYTES44 Instruction = 0x2C
|
||||
PUSHBYTES45 Instruction = 0x2D
|
||||
PUSHBYTES46 Instruction = 0x2E
|
||||
PUSHBYTES47 Instruction = 0x2F
|
||||
PUSHBYTES48 Instruction = 0x30
|
||||
PUSHBYTES49 Instruction = 0x31
|
||||
PUSHBYTES50 Instruction = 0x32
|
||||
PUSHBYTES51 Instruction = 0x33
|
||||
PUSHBYTES52 Instruction = 0x34
|
||||
PUSHBYTES53 Instruction = 0x35
|
||||
PUSHBYTES54 Instruction = 0x36
|
||||
PUSHBYTES55 Instruction = 0x37
|
||||
PUSHBYTES56 Instruction = 0x38
|
||||
PUSHBYTES57 Instruction = 0x39
|
||||
PUSHBYTES58 Instruction = 0x3A
|
||||
PUSHBYTES59 Instruction = 0x3B
|
||||
PUSHBYTES60 Instruction = 0x3C
|
||||
PUSHBYTES61 Instruction = 0x3D
|
||||
PUSHBYTES62 Instruction = 0x3E
|
||||
PUSHBYTES63 Instruction = 0x3F
|
||||
PUSHBYTES64 Instruction = 0x40
|
||||
PUSHBYTES65 Instruction = 0x41
|
||||
PUSHBYTES66 Instruction = 0x42
|
||||
PUSHBYTES67 Instruction = 0x43
|
||||
PUSHBYTES68 Instruction = 0x44
|
||||
PUSHBYTES69 Instruction = 0x45
|
||||
PUSHBYTES70 Instruction = 0x46
|
||||
PUSHBYTES71 Instruction = 0x47
|
||||
PUSHBYTES72 Instruction = 0x48
|
||||
PUSHBYTES73 Instruction = 0x49
|
||||
PUSHBYTES74 Instruction = 0x4A
|
||||
PUSHBYTES75 Instruction = 0x4B
|
||||
PUSHDATA1 Instruction = 0x4C
|
||||
PUSHDATA2 Instruction = 0x4D
|
||||
PUSHDATA4 Instruction = 0x4E
|
||||
PUSHM1 Instruction = 0x4F
|
||||
PUSH1 Instruction = 0x51
|
||||
PUSHT Instruction = PUSH1
|
||||
PUSH2 Instruction = 0x52
|
||||
PUSH3 Instruction = 0x53
|
||||
PUSH4 Instruction = 0x54
|
||||
PUSH5 Instruction = 0x55
|
||||
PUSH6 Instruction = 0x56
|
||||
PUSH7 Instruction = 0x57
|
||||
PUSH8 Instruction = 0x58
|
||||
PUSH9 Instruction = 0x59
|
||||
PUSH10 Instruction = 0x5A
|
||||
PUSH11 Instruction = 0x5B
|
||||
PUSH12 Instruction = 0x5C
|
||||
PUSH13 Instruction = 0x5D
|
||||
PUSH14 Instruction = 0x5E
|
||||
PUSH15 Instruction = 0x5F
|
||||
PUSH16 Instruction = 0x60
|
||||
|
||||
// Flow control
|
||||
NOP Instruction = 0x61
|
||||
JMP Instruction = 0x62
|
||||
JMPIF Instruction = 0x63
|
||||
JMPIFNOT Instruction = 0x64
|
||||
CALL Instruction = 0x65
|
||||
RET Instruction = 0x66
|
||||
APPCALL Instruction = 0x67
|
||||
SYSCALL Instruction = 0x68
|
||||
TAILCALL Instruction = 0x69
|
||||
|
||||
// Stack
|
||||
DUPFROMALTSTACK Instruction = 0x6A
|
||||
TOALTSTACK Instruction = 0x6B
|
||||
FROMALTSTACK Instruction = 0x6C
|
||||
XDROP Instruction = 0x6D
|
||||
XSWAP Instruction = 0x72
|
||||
XTUCK Instruction = 0x73
|
||||
DEPTH Instruction = 0x74
|
||||
DROP Instruction = 0x75
|
||||
DUP Instruction = 0x76
|
||||
NIP Instruction = 0x77
|
||||
OVER Instruction = 0x78
|
||||
PICK Instruction = 0x79
|
||||
ROLL Instruction = 0x7A
|
||||
ROT Instruction = 0x7B
|
||||
SWAP Instruction = 0x7C
|
||||
TUCK Instruction = 0x7D
|
||||
|
||||
// Splice
|
||||
CAT Instruction = 0x7E
|
||||
SUBSTR Instruction = 0x7F
|
||||
LEFT Instruction = 0x80
|
||||
RIGHT Instruction = 0x81
|
||||
SIZE Instruction = 0x82
|
||||
|
||||
// Bitwise logic
|
||||
INVERT Instruction = 0x83
|
||||
AND Instruction = 0x84
|
||||
OR Instruction = 0x85
|
||||
XOR Instruction = 0x86
|
||||
EQUAL Instruction = 0x87
|
||||
|
||||
// Arithmetic
|
||||
INC Instruction = 0x8B
|
||||
DEC Instruction = 0x8C
|
||||
SIGN Instruction = 0x8D
|
||||
NEGATE Instruction = 0x8F
|
||||
ABS Instruction = 0x90
|
||||
NOT Instruction = 0x91
|
||||
NZ Instruction = 0x92
|
||||
ADD Instruction = 0x93
|
||||
SUB Instruction = 0x94
|
||||
MUL Instruction = 0x95
|
||||
DIV Instruction = 0x96
|
||||
MOD Instruction = 0x97
|
||||
SHL Instruction = 0x98
|
||||
SHR Instruction = 0x99
|
||||
BOOLAND Instruction = 0x9A
|
||||
BOOLOR Instruction = 0x9B
|
||||
NUMEQUAL Instruction = 0x9C
|
||||
NUMNOTEQUAL Instruction = 0x9E
|
||||
LT Instruction = 0x9F
|
||||
GT Instruction = 0xA0
|
||||
LTE Instruction = 0xA1
|
||||
GTE Instruction = 0xA2
|
||||
MIN Instruction = 0xA3
|
||||
MAX Instruction = 0xA4
|
||||
WITHIN Instruction = 0xA5
|
||||
|
||||
// Crypto
|
||||
SHA1 Instruction = 0xA7
|
||||
SHA256 Instruction = 0xA8
|
||||
HASH160 Instruction = 0xA9
|
||||
HASH256 Instruction = 0xAA
|
||||
CHECKSIG Instruction = 0xAC
|
||||
VERIFY Instruction = 0xAD
|
||||
CHECKMULTISIG Instruction = 0xAE
|
||||
|
||||
// Advanced data structures (arrays, structures, maps)
|
||||
ARRAYSIZE Instruction = 0xC0
|
||||
PACK Instruction = 0xC1
|
||||
UNPACK Instruction = 0xC2
|
||||
PICKITEM Instruction = 0xC3
|
||||
SETITEM Instruction = 0xC4
|
||||
NEWARRAY Instruction = 0xC5
|
||||
NEWSTRUCT Instruction = 0xC6
|
||||
NEWMAP Instruction = 0xC7
|
||||
APPEND Instruction = 0xC8
|
||||
REVERSE Instruction = 0xC9
|
||||
REMOVE Instruction = 0xCA
|
||||
HASKEY Instruction = 0xCB
|
||||
KEYS Instruction = 0xCC
|
||||
VALUES Instruction = 0xCD
|
||||
|
||||
// Stack isolation
|
||||
CALLI Instruction = 0xE0
|
||||
CALLE Instruction = 0xE1
|
||||
CALLED Instruction = 0xE2
|
||||
CALLET Instruction = 0xE3
|
||||
CALLEDT Instruction = 0xE4
|
||||
|
||||
// Exceptions
|
||||
THROW Instruction = 0xF0
|
||||
THROWIFNOT Instruction = 0xF1
|
||||
)
|
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -154,7 +155,7 @@ func testFile(t *testing.T, filename string) {
|
|||
ctx := vm.istack.Peek(i).Value().(*Context)
|
||||
if ctx.nextip < len(ctx.prog) {
|
||||
require.Equal(t, s.InstructionPointer, ctx.nextip)
|
||||
require.Equal(t, s.Instruction, Instruction(ctx.prog[ctx.nextip]).String())
|
||||
require.Equal(t, s.Instruction, opcode.Opcode(ctx.prog[ctx.nextip]).String())
|
||||
}
|
||||
compareStacks(t, s.EStack, vm.estack)
|
||||
compareStacks(t, s.AStack, vm.astack)
|
||||
|
|
215
pkg/vm/opcode/opcode.go
Normal file
215
pkg/vm/opcode/opcode.go
Normal file
|
@ -0,0 +1,215 @@
|
|||
package opcode
|
||||
|
||||
//go:generate stringer -type=Opcode
|
||||
|
||||
// Opcode represents a single operation code for the NEO virtual machine.
|
||||
type Opcode byte
|
||||
|
||||
// Viable list of supported instruction constants.
|
||||
const (
|
||||
// Constants
|
||||
PUSH0 Opcode = 0x00
|
||||
PUSHF Opcode = PUSH0
|
||||
PUSHBYTES1 Opcode = 0x01
|
||||
PUSHBYTES2 Opcode = 0x02
|
||||
PUSHBYTES3 Opcode = 0x03
|
||||
PUSHBYTES4 Opcode = 0x04
|
||||
PUSHBYTES5 Opcode = 0x05
|
||||
PUSHBYTES6 Opcode = 0x06
|
||||
PUSHBYTES7 Opcode = 0x07
|
||||
PUSHBYTES8 Opcode = 0x08
|
||||
PUSHBYTES9 Opcode = 0x09
|
||||
PUSHBYTES10 Opcode = 0x0A
|
||||
PUSHBYTES11 Opcode = 0x0B
|
||||
PUSHBYTES12 Opcode = 0x0C
|
||||
PUSHBYTES13 Opcode = 0x0D
|
||||
PUSHBYTES14 Opcode = 0x0E
|
||||
PUSHBYTES15 Opcode = 0x0F
|
||||
PUSHBYTES16 Opcode = 0x10
|
||||
PUSHBYTES17 Opcode = 0x11
|
||||
PUSHBYTES18 Opcode = 0x12
|
||||
PUSHBYTES19 Opcode = 0x13
|
||||
PUSHBYTES20 Opcode = 0x14
|
||||
PUSHBYTES21 Opcode = 0x15
|
||||
PUSHBYTES22 Opcode = 0x16
|
||||
PUSHBYTES23 Opcode = 0x17
|
||||
PUSHBYTES24 Opcode = 0x18
|
||||
PUSHBYTES25 Opcode = 0x19
|
||||
PUSHBYTES26 Opcode = 0x1A
|
||||
PUSHBYTES27 Opcode = 0x1B
|
||||
PUSHBYTES28 Opcode = 0x1C
|
||||
PUSHBYTES29 Opcode = 0x1D
|
||||
PUSHBYTES30 Opcode = 0x1E
|
||||
PUSHBYTES31 Opcode = 0x1F
|
||||
PUSHBYTES32 Opcode = 0x20
|
||||
PUSHBYTES33 Opcode = 0x21
|
||||
PUSHBYTES34 Opcode = 0x22
|
||||
PUSHBYTES35 Opcode = 0x23
|
||||
PUSHBYTES36 Opcode = 0x24
|
||||
PUSHBYTES37 Opcode = 0x25
|
||||
PUSHBYTES38 Opcode = 0x26
|
||||
PUSHBYTES39 Opcode = 0x27
|
||||
PUSHBYTES40 Opcode = 0x28
|
||||
PUSHBYTES41 Opcode = 0x29
|
||||
PUSHBYTES42 Opcode = 0x2A
|
||||
PUSHBYTES43 Opcode = 0x2B
|
||||
PUSHBYTES44 Opcode = 0x2C
|
||||
PUSHBYTES45 Opcode = 0x2D
|
||||
PUSHBYTES46 Opcode = 0x2E
|
||||
PUSHBYTES47 Opcode = 0x2F
|
||||
PUSHBYTES48 Opcode = 0x30
|
||||
PUSHBYTES49 Opcode = 0x31
|
||||
PUSHBYTES50 Opcode = 0x32
|
||||
PUSHBYTES51 Opcode = 0x33
|
||||
PUSHBYTES52 Opcode = 0x34
|
||||
PUSHBYTES53 Opcode = 0x35
|
||||
PUSHBYTES54 Opcode = 0x36
|
||||
PUSHBYTES55 Opcode = 0x37
|
||||
PUSHBYTES56 Opcode = 0x38
|
||||
PUSHBYTES57 Opcode = 0x39
|
||||
PUSHBYTES58 Opcode = 0x3A
|
||||
PUSHBYTES59 Opcode = 0x3B
|
||||
PUSHBYTES60 Opcode = 0x3C
|
||||
PUSHBYTES61 Opcode = 0x3D
|
||||
PUSHBYTES62 Opcode = 0x3E
|
||||
PUSHBYTES63 Opcode = 0x3F
|
||||
PUSHBYTES64 Opcode = 0x40
|
||||
PUSHBYTES65 Opcode = 0x41
|
||||
PUSHBYTES66 Opcode = 0x42
|
||||
PUSHBYTES67 Opcode = 0x43
|
||||
PUSHBYTES68 Opcode = 0x44
|
||||
PUSHBYTES69 Opcode = 0x45
|
||||
PUSHBYTES70 Opcode = 0x46
|
||||
PUSHBYTES71 Opcode = 0x47
|
||||
PUSHBYTES72 Opcode = 0x48
|
||||
PUSHBYTES73 Opcode = 0x49
|
||||
PUSHBYTES74 Opcode = 0x4A
|
||||
PUSHBYTES75 Opcode = 0x4B
|
||||
PUSHDATA1 Opcode = 0x4C
|
||||
PUSHDATA2 Opcode = 0x4D
|
||||
PUSHDATA4 Opcode = 0x4E
|
||||
PUSHM1 Opcode = 0x4F
|
||||
PUSH1 Opcode = 0x51
|
||||
PUSHT Opcode = PUSH1
|
||||
PUSH2 Opcode = 0x52
|
||||
PUSH3 Opcode = 0x53
|
||||
PUSH4 Opcode = 0x54
|
||||
PUSH5 Opcode = 0x55
|
||||
PUSH6 Opcode = 0x56
|
||||
PUSH7 Opcode = 0x57
|
||||
PUSH8 Opcode = 0x58
|
||||
PUSH9 Opcode = 0x59
|
||||
PUSH10 Opcode = 0x5A
|
||||
PUSH11 Opcode = 0x5B
|
||||
PUSH12 Opcode = 0x5C
|
||||
PUSH13 Opcode = 0x5D
|
||||
PUSH14 Opcode = 0x5E
|
||||
PUSH15 Opcode = 0x5F
|
||||
PUSH16 Opcode = 0x60
|
||||
|
||||
// Flow control
|
||||
NOP Opcode = 0x61
|
||||
JMP Opcode = 0x62
|
||||
JMPIF Opcode = 0x63
|
||||
JMPIFNOT Opcode = 0x64
|
||||
CALL Opcode = 0x65
|
||||
RET Opcode = 0x66
|
||||
APPCALL Opcode = 0x67
|
||||
SYSCALL Opcode = 0x68
|
||||
TAILCALL Opcode = 0x69
|
||||
|
||||
// Stack
|
||||
DUPFROMALTSTACK Opcode = 0x6A
|
||||
TOALTSTACK Opcode = 0x6B
|
||||
FROMALTSTACK Opcode = 0x6C
|
||||
XDROP Opcode = 0x6D
|
||||
XSWAP Opcode = 0x72
|
||||
XTUCK Opcode = 0x73
|
||||
DEPTH Opcode = 0x74
|
||||
DROP Opcode = 0x75
|
||||
DUP Opcode = 0x76
|
||||
NIP Opcode = 0x77
|
||||
OVER Opcode = 0x78
|
||||
PICK Opcode = 0x79
|
||||
ROLL Opcode = 0x7A
|
||||
ROT Opcode = 0x7B
|
||||
SWAP Opcode = 0x7C
|
||||
TUCK Opcode = 0x7D
|
||||
|
||||
// Splice
|
||||
CAT Opcode = 0x7E
|
||||
SUBSTR Opcode = 0x7F
|
||||
LEFT Opcode = 0x80
|
||||
RIGHT Opcode = 0x81
|
||||
SIZE Opcode = 0x82
|
||||
|
||||
// Bitwise logic
|
||||
INVERT Opcode = 0x83
|
||||
AND Opcode = 0x84
|
||||
OR Opcode = 0x85
|
||||
XOR Opcode = 0x86
|
||||
EQUAL Opcode = 0x87
|
||||
|
||||
// Arithmetic
|
||||
INC Opcode = 0x8B
|
||||
DEC Opcode = 0x8C
|
||||
SIGN Opcode = 0x8D
|
||||
NEGATE Opcode = 0x8F
|
||||
ABS Opcode = 0x90
|
||||
NOT Opcode = 0x91
|
||||
NZ Opcode = 0x92
|
||||
ADD Opcode = 0x93
|
||||
SUB Opcode = 0x94
|
||||
MUL Opcode = 0x95
|
||||
DIV Opcode = 0x96
|
||||
MOD Opcode = 0x97
|
||||
SHL Opcode = 0x98
|
||||
SHR Opcode = 0x99
|
||||
BOOLAND Opcode = 0x9A
|
||||
BOOLOR Opcode = 0x9B
|
||||
NUMEQUAL Opcode = 0x9C
|
||||
NUMNOTEQUAL Opcode = 0x9E
|
||||
LT Opcode = 0x9F
|
||||
GT Opcode = 0xA0
|
||||
LTE Opcode = 0xA1
|
||||
GTE Opcode = 0xA2
|
||||
MIN Opcode = 0xA3
|
||||
MAX Opcode = 0xA4
|
||||
WITHIN Opcode = 0xA5
|
||||
|
||||
// Crypto
|
||||
SHA1 Opcode = 0xA7
|
||||
SHA256 Opcode = 0xA8
|
||||
HASH160 Opcode = 0xA9
|
||||
HASH256 Opcode = 0xAA
|
||||
CHECKSIG Opcode = 0xAC
|
||||
VERIFY Opcode = 0xAD
|
||||
CHECKMULTISIG Opcode = 0xAE
|
||||
|
||||
// Advanced data structures (arrays, structures, maps)
|
||||
ARRAYSIZE Opcode = 0xC0
|
||||
PACK Opcode = 0xC1
|
||||
UNPACK Opcode = 0xC2
|
||||
PICKITEM Opcode = 0xC3
|
||||
SETITEM Opcode = 0xC4
|
||||
NEWARRAY Opcode = 0xC5
|
||||
NEWSTRUCT Opcode = 0xC6
|
||||
NEWMAP Opcode = 0xC7
|
||||
APPEND Opcode = 0xC8
|
||||
REVERSE Opcode = 0xC9
|
||||
REMOVE Opcode = 0xCA
|
||||
HASKEY Opcode = 0xCB
|
||||
KEYS Opcode = 0xCC
|
||||
VALUES Opcode = 0xCD
|
||||
|
||||
// Stack isolation
|
||||
CALLI Opcode = 0xE0
|
||||
CALLE Opcode = 0xE1
|
||||
CALLED Opcode = 0xE2
|
||||
CALLET Opcode = 0xE3
|
||||
CALLEDT Opcode = 0xE4
|
||||
|
||||
// Exceptions
|
||||
THROW Opcode = 0xF0
|
||||
THROWIFNOT Opcode = 0xF1
|
||||
)
|
393
pkg/vm/opcode/opcode_string.go
Normal file
393
pkg/vm/opcode/opcode_string.go
Normal file
|
@ -0,0 +1,393 @@
|
|||
// Code generated by "stringer -type=Opcode"; DO NOT EDIT.
|
||||
|
||||
package opcode
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[PUSH0-0]
|
||||
_ = x[PUSHF-0]
|
||||
_ = x[PUSHBYTES1-1]
|
||||
_ = x[PUSHBYTES2-2]
|
||||
_ = x[PUSHBYTES3-3]
|
||||
_ = x[PUSHBYTES4-4]
|
||||
_ = x[PUSHBYTES5-5]
|
||||
_ = x[PUSHBYTES6-6]
|
||||
_ = x[PUSHBYTES7-7]
|
||||
_ = x[PUSHBYTES8-8]
|
||||
_ = x[PUSHBYTES9-9]
|
||||
_ = x[PUSHBYTES10-10]
|
||||
_ = x[PUSHBYTES11-11]
|
||||
_ = x[PUSHBYTES12-12]
|
||||
_ = x[PUSHBYTES13-13]
|
||||
_ = x[PUSHBYTES14-14]
|
||||
_ = x[PUSHBYTES15-15]
|
||||
_ = x[PUSHBYTES16-16]
|
||||
_ = x[PUSHBYTES17-17]
|
||||
_ = x[PUSHBYTES18-18]
|
||||
_ = x[PUSHBYTES19-19]
|
||||
_ = x[PUSHBYTES20-20]
|
||||
_ = x[PUSHBYTES21-21]
|
||||
_ = x[PUSHBYTES22-22]
|
||||
_ = x[PUSHBYTES23-23]
|
||||
_ = x[PUSHBYTES24-24]
|
||||
_ = x[PUSHBYTES25-25]
|
||||
_ = x[PUSHBYTES26-26]
|
||||
_ = x[PUSHBYTES27-27]
|
||||
_ = x[PUSHBYTES28-28]
|
||||
_ = x[PUSHBYTES29-29]
|
||||
_ = x[PUSHBYTES30-30]
|
||||
_ = x[PUSHBYTES31-31]
|
||||
_ = x[PUSHBYTES32-32]
|
||||
_ = x[PUSHBYTES33-33]
|
||||
_ = x[PUSHBYTES34-34]
|
||||
_ = x[PUSHBYTES35-35]
|
||||
_ = x[PUSHBYTES36-36]
|
||||
_ = x[PUSHBYTES37-37]
|
||||
_ = x[PUSHBYTES38-38]
|
||||
_ = x[PUSHBYTES39-39]
|
||||
_ = x[PUSHBYTES40-40]
|
||||
_ = x[PUSHBYTES41-41]
|
||||
_ = x[PUSHBYTES42-42]
|
||||
_ = x[PUSHBYTES43-43]
|
||||
_ = x[PUSHBYTES44-44]
|
||||
_ = x[PUSHBYTES45-45]
|
||||
_ = x[PUSHBYTES46-46]
|
||||
_ = x[PUSHBYTES47-47]
|
||||
_ = x[PUSHBYTES48-48]
|
||||
_ = x[PUSHBYTES49-49]
|
||||
_ = x[PUSHBYTES50-50]
|
||||
_ = x[PUSHBYTES51-51]
|
||||
_ = x[PUSHBYTES52-52]
|
||||
_ = x[PUSHBYTES53-53]
|
||||
_ = x[PUSHBYTES54-54]
|
||||
_ = x[PUSHBYTES55-55]
|
||||
_ = x[PUSHBYTES56-56]
|
||||
_ = x[PUSHBYTES57-57]
|
||||
_ = x[PUSHBYTES58-58]
|
||||
_ = x[PUSHBYTES59-59]
|
||||
_ = x[PUSHBYTES60-60]
|
||||
_ = x[PUSHBYTES61-61]
|
||||
_ = x[PUSHBYTES62-62]
|
||||
_ = x[PUSHBYTES63-63]
|
||||
_ = x[PUSHBYTES64-64]
|
||||
_ = x[PUSHBYTES65-65]
|
||||
_ = x[PUSHBYTES66-66]
|
||||
_ = x[PUSHBYTES67-67]
|
||||
_ = x[PUSHBYTES68-68]
|
||||
_ = x[PUSHBYTES69-69]
|
||||
_ = x[PUSHBYTES70-70]
|
||||
_ = x[PUSHBYTES71-71]
|
||||
_ = x[PUSHBYTES72-72]
|
||||
_ = x[PUSHBYTES73-73]
|
||||
_ = x[PUSHBYTES74-74]
|
||||
_ = x[PUSHBYTES75-75]
|
||||
_ = x[PUSHDATA1-76]
|
||||
_ = x[PUSHDATA2-77]
|
||||
_ = x[PUSHDATA4-78]
|
||||
_ = x[PUSHM1-79]
|
||||
_ = x[PUSH1-81]
|
||||
_ = x[PUSHT-81]
|
||||
_ = x[PUSH2-82]
|
||||
_ = x[PUSH3-83]
|
||||
_ = x[PUSH4-84]
|
||||
_ = x[PUSH5-85]
|
||||
_ = x[PUSH6-86]
|
||||
_ = x[PUSH7-87]
|
||||
_ = x[PUSH8-88]
|
||||
_ = x[PUSH9-89]
|
||||
_ = x[PUSH10-90]
|
||||
_ = x[PUSH11-91]
|
||||
_ = x[PUSH12-92]
|
||||
_ = x[PUSH13-93]
|
||||
_ = x[PUSH14-94]
|
||||
_ = x[PUSH15-95]
|
||||
_ = x[PUSH16-96]
|
||||
_ = x[NOP-97]
|
||||
_ = x[JMP-98]
|
||||
_ = x[JMPIF-99]
|
||||
_ = x[JMPIFNOT-100]
|
||||
_ = x[CALL-101]
|
||||
_ = x[RET-102]
|
||||
_ = x[APPCALL-103]
|
||||
_ = x[SYSCALL-104]
|
||||
_ = x[TAILCALL-105]
|
||||
_ = x[DUPFROMALTSTACK-106]
|
||||
_ = x[TOALTSTACK-107]
|
||||
_ = x[FROMALTSTACK-108]
|
||||
_ = x[XDROP-109]
|
||||
_ = x[XSWAP-114]
|
||||
_ = x[XTUCK-115]
|
||||
_ = x[DEPTH-116]
|
||||
_ = x[DROP-117]
|
||||
_ = x[DUP-118]
|
||||
_ = x[NIP-119]
|
||||
_ = x[OVER-120]
|
||||
_ = x[PICK-121]
|
||||
_ = x[ROLL-122]
|
||||
_ = x[ROT-123]
|
||||
_ = x[SWAP-124]
|
||||
_ = x[TUCK-125]
|
||||
_ = x[CAT-126]
|
||||
_ = x[SUBSTR-127]
|
||||
_ = x[LEFT-128]
|
||||
_ = x[RIGHT-129]
|
||||
_ = x[SIZE-130]
|
||||
_ = x[INVERT-131]
|
||||
_ = x[AND-132]
|
||||
_ = x[OR-133]
|
||||
_ = x[XOR-134]
|
||||
_ = x[EQUAL-135]
|
||||
_ = x[INC-139]
|
||||
_ = x[DEC-140]
|
||||
_ = x[SIGN-141]
|
||||
_ = x[NEGATE-143]
|
||||
_ = x[ABS-144]
|
||||
_ = x[NOT-145]
|
||||
_ = x[NZ-146]
|
||||
_ = x[ADD-147]
|
||||
_ = x[SUB-148]
|
||||
_ = x[MUL-149]
|
||||
_ = x[DIV-150]
|
||||
_ = x[MOD-151]
|
||||
_ = x[SHL-152]
|
||||
_ = x[SHR-153]
|
||||
_ = x[BOOLAND-154]
|
||||
_ = x[BOOLOR-155]
|
||||
_ = x[NUMEQUAL-156]
|
||||
_ = x[NUMNOTEQUAL-158]
|
||||
_ = x[LT-159]
|
||||
_ = x[GT-160]
|
||||
_ = x[LTE-161]
|
||||
_ = x[GTE-162]
|
||||
_ = x[MIN-163]
|
||||
_ = x[MAX-164]
|
||||
_ = x[WITHIN-165]
|
||||
_ = x[SHA1-167]
|
||||
_ = x[SHA256-168]
|
||||
_ = x[HASH160-169]
|
||||
_ = x[HASH256-170]
|
||||
_ = x[CHECKSIG-172]
|
||||
_ = x[VERIFY-173]
|
||||
_ = x[CHECKMULTISIG-174]
|
||||
_ = x[ARRAYSIZE-192]
|
||||
_ = x[PACK-193]
|
||||
_ = x[UNPACK-194]
|
||||
_ = x[PICKITEM-195]
|
||||
_ = x[SETITEM-196]
|
||||
_ = x[NEWARRAY-197]
|
||||
_ = x[NEWSTRUCT-198]
|
||||
_ = x[NEWMAP-199]
|
||||
_ = x[APPEND-200]
|
||||
_ = x[REVERSE-201]
|
||||
_ = x[REMOVE-202]
|
||||
_ = x[HASKEY-203]
|
||||
_ = x[KEYS-204]
|
||||
_ = x[VALUES-205]
|
||||
_ = x[CALLI-224]
|
||||
_ = x[CALLE-225]
|
||||
_ = x[CALLED-226]
|
||||
_ = x[CALLET-227]
|
||||
_ = x[CALLEDT-228]
|
||||
_ = x[THROW-240]
|
||||
_ = x[THROWIFNOT-241]
|
||||
}
|
||||
|
||||
const _Opcode_name = "PUSH0PUSHBYTES1PUSHBYTES2PUSHBYTES3PUSHBYTES4PUSHBYTES5PUSHBYTES6PUSHBYTES7PUSHBYTES8PUSHBYTES9PUSHBYTES10PUSHBYTES11PUSHBYTES12PUSHBYTES13PUSHBYTES14PUSHBYTES15PUSHBYTES16PUSHBYTES17PUSHBYTES18PUSHBYTES19PUSHBYTES20PUSHBYTES21PUSHBYTES22PUSHBYTES23PUSHBYTES24PUSHBYTES25PUSHBYTES26PUSHBYTES27PUSHBYTES28PUSHBYTES29PUSHBYTES30PUSHBYTES31PUSHBYTES32PUSHBYTES33PUSHBYTES34PUSHBYTES35PUSHBYTES36PUSHBYTES37PUSHBYTES38PUSHBYTES39PUSHBYTES40PUSHBYTES41PUSHBYTES42PUSHBYTES43PUSHBYTES44PUSHBYTES45PUSHBYTES46PUSHBYTES47PUSHBYTES48PUSHBYTES49PUSHBYTES50PUSHBYTES51PUSHBYTES52PUSHBYTES53PUSHBYTES54PUSHBYTES55PUSHBYTES56PUSHBYTES57PUSHBYTES58PUSHBYTES59PUSHBYTES60PUSHBYTES61PUSHBYTES62PUSHBYTES63PUSHBYTES64PUSHBYTES65PUSHBYTES66PUSHBYTES67PUSHBYTES68PUSHBYTES69PUSHBYTES70PUSHBYTES71PUSHBYTES72PUSHBYTES73PUSHBYTES74PUSHBYTES75PUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPIFJMPIFNOTCALLRETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTSIZEINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGARRAYSIZEPACKUNPACKPICKITEMSETITEMNEWARRAYNEWSTRUCTNEWMAPAPPENDREVERSEREMOVEHASKEYKEYSVALUESCALLICALLECALLEDCALLETCALLEDTTHROWTHROWIFNOT"
|
||||
|
||||
var _Opcode_map = map[Opcode]string{
|
||||
0: _Opcode_name[0:5],
|
||||
1: _Opcode_name[5:15],
|
||||
2: _Opcode_name[15:25],
|
||||
3: _Opcode_name[25:35],
|
||||
4: _Opcode_name[35:45],
|
||||
5: _Opcode_name[45:55],
|
||||
6: _Opcode_name[55:65],
|
||||
7: _Opcode_name[65:75],
|
||||
8: _Opcode_name[75:85],
|
||||
9: _Opcode_name[85:95],
|
||||
10: _Opcode_name[95:106],
|
||||
11: _Opcode_name[106:117],
|
||||
12: _Opcode_name[117:128],
|
||||
13: _Opcode_name[128:139],
|
||||
14: _Opcode_name[139:150],
|
||||
15: _Opcode_name[150:161],
|
||||
16: _Opcode_name[161:172],
|
||||
17: _Opcode_name[172:183],
|
||||
18: _Opcode_name[183:194],
|
||||
19: _Opcode_name[194:205],
|
||||
20: _Opcode_name[205:216],
|
||||
21: _Opcode_name[216:227],
|
||||
22: _Opcode_name[227:238],
|
||||
23: _Opcode_name[238:249],
|
||||
24: _Opcode_name[249:260],
|
||||
25: _Opcode_name[260:271],
|
||||
26: _Opcode_name[271:282],
|
||||
27: _Opcode_name[282:293],
|
||||
28: _Opcode_name[293:304],
|
||||
29: _Opcode_name[304:315],
|
||||
30: _Opcode_name[315:326],
|
||||
31: _Opcode_name[326:337],
|
||||
32: _Opcode_name[337:348],
|
||||
33: _Opcode_name[348:359],
|
||||
34: _Opcode_name[359:370],
|
||||
35: _Opcode_name[370:381],
|
||||
36: _Opcode_name[381:392],
|
||||
37: _Opcode_name[392:403],
|
||||
38: _Opcode_name[403:414],
|
||||
39: _Opcode_name[414:425],
|
||||
40: _Opcode_name[425:436],
|
||||
41: _Opcode_name[436:447],
|
||||
42: _Opcode_name[447:458],
|
||||
43: _Opcode_name[458:469],
|
||||
44: _Opcode_name[469:480],
|
||||
45: _Opcode_name[480:491],
|
||||
46: _Opcode_name[491:502],
|
||||
47: _Opcode_name[502:513],
|
||||
48: _Opcode_name[513:524],
|
||||
49: _Opcode_name[524:535],
|
||||
50: _Opcode_name[535:546],
|
||||
51: _Opcode_name[546:557],
|
||||
52: _Opcode_name[557:568],
|
||||
53: _Opcode_name[568:579],
|
||||
54: _Opcode_name[579:590],
|
||||
55: _Opcode_name[590:601],
|
||||
56: _Opcode_name[601:612],
|
||||
57: _Opcode_name[612:623],
|
||||
58: _Opcode_name[623:634],
|
||||
59: _Opcode_name[634:645],
|
||||
60: _Opcode_name[645:656],
|
||||
61: _Opcode_name[656:667],
|
||||
62: _Opcode_name[667:678],
|
||||
63: _Opcode_name[678:689],
|
||||
64: _Opcode_name[689:700],
|
||||
65: _Opcode_name[700:711],
|
||||
66: _Opcode_name[711:722],
|
||||
67: _Opcode_name[722:733],
|
||||
68: _Opcode_name[733:744],
|
||||
69: _Opcode_name[744:755],
|
||||
70: _Opcode_name[755:766],
|
||||
71: _Opcode_name[766:777],
|
||||
72: _Opcode_name[777:788],
|
||||
73: _Opcode_name[788:799],
|
||||
74: _Opcode_name[799:810],
|
||||
75: _Opcode_name[810:821],
|
||||
76: _Opcode_name[821:830],
|
||||
77: _Opcode_name[830:839],
|
||||
78: _Opcode_name[839:848],
|
||||
79: _Opcode_name[848:854],
|
||||
81: _Opcode_name[854:859],
|
||||
82: _Opcode_name[859:864],
|
||||
83: _Opcode_name[864:869],
|
||||
84: _Opcode_name[869:874],
|
||||
85: _Opcode_name[874:879],
|
||||
86: _Opcode_name[879:884],
|
||||
87: _Opcode_name[884:889],
|
||||
88: _Opcode_name[889:894],
|
||||
89: _Opcode_name[894:899],
|
||||
90: _Opcode_name[899:905],
|
||||
91: _Opcode_name[905:911],
|
||||
92: _Opcode_name[911:917],
|
||||
93: _Opcode_name[917:923],
|
||||
94: _Opcode_name[923:929],
|
||||
95: _Opcode_name[929:935],
|
||||
96: _Opcode_name[935:941],
|
||||
97: _Opcode_name[941:944],
|
||||
98: _Opcode_name[944:947],
|
||||
99: _Opcode_name[947:952],
|
||||
100: _Opcode_name[952:960],
|
||||
101: _Opcode_name[960:964],
|
||||
102: _Opcode_name[964:967],
|
||||
103: _Opcode_name[967:974],
|
||||
104: _Opcode_name[974:981],
|
||||
105: _Opcode_name[981:989],
|
||||
106: _Opcode_name[989:1004],
|
||||
107: _Opcode_name[1004:1014],
|
||||
108: _Opcode_name[1014:1026],
|
||||
109: _Opcode_name[1026:1031],
|
||||
114: _Opcode_name[1031:1036],
|
||||
115: _Opcode_name[1036:1041],
|
||||
116: _Opcode_name[1041:1046],
|
||||
117: _Opcode_name[1046:1050],
|
||||
118: _Opcode_name[1050:1053],
|
||||
119: _Opcode_name[1053:1056],
|
||||
120: _Opcode_name[1056:1060],
|
||||
121: _Opcode_name[1060:1064],
|
||||
122: _Opcode_name[1064:1068],
|
||||
123: _Opcode_name[1068:1071],
|
||||
124: _Opcode_name[1071:1075],
|
||||
125: _Opcode_name[1075:1079],
|
||||
126: _Opcode_name[1079:1082],
|
||||
127: _Opcode_name[1082:1088],
|
||||
128: _Opcode_name[1088:1092],
|
||||
129: _Opcode_name[1092:1097],
|
||||
130: _Opcode_name[1097:1101],
|
||||
131: _Opcode_name[1101:1107],
|
||||
132: _Opcode_name[1107:1110],
|
||||
133: _Opcode_name[1110:1112],
|
||||
134: _Opcode_name[1112:1115],
|
||||
135: _Opcode_name[1115:1120],
|
||||
139: _Opcode_name[1120:1123],
|
||||
140: _Opcode_name[1123:1126],
|
||||
141: _Opcode_name[1126:1130],
|
||||
143: _Opcode_name[1130:1136],
|
||||
144: _Opcode_name[1136:1139],
|
||||
145: _Opcode_name[1139:1142],
|
||||
146: _Opcode_name[1142:1144],
|
||||
147: _Opcode_name[1144:1147],
|
||||
148: _Opcode_name[1147:1150],
|
||||
149: _Opcode_name[1150:1153],
|
||||
150: _Opcode_name[1153:1156],
|
||||
151: _Opcode_name[1156:1159],
|
||||
152: _Opcode_name[1159:1162],
|
||||
153: _Opcode_name[1162:1165],
|
||||
154: _Opcode_name[1165:1172],
|
||||
155: _Opcode_name[1172:1178],
|
||||
156: _Opcode_name[1178:1186],
|
||||
158: _Opcode_name[1186:1197],
|
||||
159: _Opcode_name[1197:1199],
|
||||
160: _Opcode_name[1199:1201],
|
||||
161: _Opcode_name[1201:1204],
|
||||
162: _Opcode_name[1204:1207],
|
||||
163: _Opcode_name[1207:1210],
|
||||
164: _Opcode_name[1210:1213],
|
||||
165: _Opcode_name[1213:1219],
|
||||
167: _Opcode_name[1219:1223],
|
||||
168: _Opcode_name[1223:1229],
|
||||
169: _Opcode_name[1229:1236],
|
||||
170: _Opcode_name[1236:1243],
|
||||
172: _Opcode_name[1243:1251],
|
||||
173: _Opcode_name[1251:1257],
|
||||
174: _Opcode_name[1257:1270],
|
||||
192: _Opcode_name[1270:1279],
|
||||
193: _Opcode_name[1279:1283],
|
||||
194: _Opcode_name[1283:1289],
|
||||
195: _Opcode_name[1289:1297],
|
||||
196: _Opcode_name[1297:1304],
|
||||
197: _Opcode_name[1304:1312],
|
||||
198: _Opcode_name[1312:1321],
|
||||
199: _Opcode_name[1321:1327],
|
||||
200: _Opcode_name[1327:1333],
|
||||
201: _Opcode_name[1333:1340],
|
||||
202: _Opcode_name[1340:1346],
|
||||
203: _Opcode_name[1346:1352],
|
||||
204: _Opcode_name[1352:1356],
|
||||
205: _Opcode_name[1356:1362],
|
||||
224: _Opcode_name[1362:1367],
|
||||
225: _Opcode_name[1367:1372],
|
||||
226: _Opcode_name[1372:1378],
|
||||
227: _Opcode_name[1378:1384],
|
||||
228: _Opcode_name[1384:1391],
|
||||
240: _Opcode_name[1391:1396],
|
||||
241: _Opcode_name[1396:1406],
|
||||
}
|
||||
|
||||
func (i Opcode) String() string {
|
||||
if str, ok := _Opcode_map[i]; ok {
|
||||
return str
|
||||
}
|
||||
return "Opcode(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
20
pkg/vm/opcode/opcode_test.go
Normal file
20
pkg/vm/opcode/opcode_test.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package opcode
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Nothing more to test here, really.
|
||||
func TestStringer(t *testing.T) {
|
||||
tests := map[Opcode]string{
|
||||
ADD: "ADD",
|
||||
SUB: "SUB",
|
||||
THROWIFNOT: "THROWIFNOT",
|
||||
0xff: "Opcode(255)",
|
||||
}
|
||||
for o, s := range tests {
|
||||
assert.Equal(t, s, o.String())
|
||||
}
|
||||
}
|
211
pkg/vm/vm.go
211
pkg/vm/vm.go
|
@ -14,12 +14,13 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type errorAtInstruct struct {
|
||||
ip int
|
||||
op Instruction
|
||||
op opcode.Opcode
|
||||
err interface{}
|
||||
}
|
||||
|
||||
|
@ -27,7 +28,7 @@ func (e *errorAtInstruct) Error() string {
|
|||
return fmt.Sprintf("error encountered at instruction %d (%s): %s", e.ip, e.op, e.err)
|
||||
}
|
||||
|
||||
func newError(ip int, op Instruction, err interface{}) *errorAtInstruct {
|
||||
func newError(ip int, op opcode.Opcode, err interface{}) *errorAtInstruct {
|
||||
return &errorAtInstruct{ip: ip, op: op, err: err}
|
||||
}
|
||||
|
||||
|
@ -175,12 +176,12 @@ func (v *VM) PrintOps() {
|
|||
var desc = ""
|
||||
if parameter != nil {
|
||||
switch instr {
|
||||
case JMP, JMPIF, JMPIFNOT, CALL:
|
||||
case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.CALL:
|
||||
offset := int16(binary.LittleEndian.Uint16(parameter))
|
||||
desc = fmt.Sprintf("%d (%d/%x)", ctx.ip+int(offset), offset, parameter)
|
||||
case SYSCALL:
|
||||
case opcode.SYSCALL:
|
||||
desc = fmt.Sprintf("%q", parameter)
|
||||
case APPCALL, TAILCALL:
|
||||
case opcode.APPCALL, opcode.TAILCALL:
|
||||
desc = fmt.Sprintf("%x", parameter)
|
||||
default:
|
||||
if utf8.Valid(parameter) {
|
||||
|
@ -447,7 +448,7 @@ func (v *VM) SetScriptGetter(gs func(util.Uint160) []byte) {
|
|||
}
|
||||
|
||||
// execute performs an instruction cycle in the VM. Acting on the instruction (opcode).
|
||||
func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error) {
|
||||
func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err error) {
|
||||
// Instead of polluting the whole VM logic with error handling, we will recover
|
||||
// each panic at a central point, putting the VM in a fault state and setting error.
|
||||
defer func() {
|
||||
|
@ -460,44 +461,46 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
}()
|
||||
|
||||
if op >= PUSHBYTES1 && op <= PUSHBYTES75 {
|
||||
if op >= opcode.PUSHBYTES1 && op <= opcode.PUSHBYTES75 {
|
||||
v.estack.PushVal(parameter)
|
||||
return
|
||||
}
|
||||
|
||||
switch op {
|
||||
case PUSHM1, PUSH1, PUSH2, PUSH3, PUSH4, PUSH5,
|
||||
PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11,
|
||||
PUSH12, PUSH13, PUSH14, PUSH15, PUSH16:
|
||||
val := int(op) - int(PUSH1) + 1
|
||||
case opcode.PUSHM1, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3,
|
||||
opcode.PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7,
|
||||
opcode.PUSH8, opcode.PUSH9, opcode.PUSH10, opcode.PUSH11,
|
||||
opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15,
|
||||
opcode.PUSH16:
|
||||
val := int(op) - int(opcode.PUSH1) + 1
|
||||
v.estack.PushVal(val)
|
||||
|
||||
case PUSH0:
|
||||
case opcode.PUSH0:
|
||||
v.estack.PushVal([]byte{})
|
||||
|
||||
case PUSHDATA1, PUSHDATA2, PUSHDATA4:
|
||||
case opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4:
|
||||
v.estack.PushVal(parameter)
|
||||
|
||||
// Stack operations.
|
||||
case TOALTSTACK:
|
||||
case opcode.TOALTSTACK:
|
||||
v.astack.Push(v.estack.Pop())
|
||||
|
||||
case FROMALTSTACK:
|
||||
case opcode.FROMALTSTACK:
|
||||
v.estack.Push(v.astack.Pop())
|
||||
|
||||
case DUPFROMALTSTACK:
|
||||
case opcode.DUPFROMALTSTACK:
|
||||
v.estack.Push(v.astack.Dup(0))
|
||||
|
||||
case DUP:
|
||||
case opcode.DUP:
|
||||
v.estack.Push(v.estack.Dup(0))
|
||||
|
||||
case SWAP:
|
||||
case opcode.SWAP:
|
||||
a := v.estack.Pop()
|
||||
b := v.estack.Pop()
|
||||
v.estack.Push(a)
|
||||
v.estack.Push(b)
|
||||
|
||||
case TUCK:
|
||||
case opcode.TUCK:
|
||||
a := v.estack.Dup(0)
|
||||
if a == nil {
|
||||
panic("no top-level element found")
|
||||
|
@ -507,7 +510,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.InsertAt(a, 2)
|
||||
|
||||
case CAT:
|
||||
case opcode.CAT:
|
||||
b := v.estack.Pop().Bytes()
|
||||
a := v.estack.Pop().Bytes()
|
||||
if l := len(a) + len(b); l > MaxItemSize {
|
||||
|
@ -516,7 +519,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
ab := append(a, b...)
|
||||
v.estack.PushVal(ab)
|
||||
|
||||
case SUBSTR:
|
||||
case opcode.SUBSTR:
|
||||
l := int(v.estack.Pop().BigInt().Int64())
|
||||
if l < 0 {
|
||||
panic("negative length")
|
||||
|
@ -538,7 +541,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.PushVal(s[o:last])
|
||||
|
||||
case LEFT:
|
||||
case opcode.LEFT:
|
||||
l := int(v.estack.Pop().BigInt().Int64())
|
||||
if l < 0 {
|
||||
panic("negative length")
|
||||
|
@ -549,7 +552,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.PushVal(s[:l])
|
||||
|
||||
case RIGHT:
|
||||
case opcode.RIGHT:
|
||||
l := int(v.estack.Pop().BigInt().Int64())
|
||||
if l < 0 {
|
||||
panic("negative length")
|
||||
|
@ -557,7 +560,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
s := v.estack.Pop().Bytes()
|
||||
v.estack.PushVal(s[len(s)-l:])
|
||||
|
||||
case XDROP:
|
||||
case opcode.XDROP:
|
||||
n := int(v.estack.Pop().BigInt().Int64())
|
||||
if n < 0 {
|
||||
panic("invalid length")
|
||||
|
@ -567,7 +570,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
panic("bad index")
|
||||
}
|
||||
|
||||
case XSWAP:
|
||||
case opcode.XSWAP:
|
||||
n := int(v.estack.Pop().BigInt().Int64())
|
||||
if n < 0 {
|
||||
panic("XSWAP: invalid length")
|
||||
|
@ -583,7 +586,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
b.value = aval
|
||||
}
|
||||
|
||||
case XTUCK:
|
||||
case opcode.XTUCK:
|
||||
n := int(v.estack.Pop().BigInt().Int64())
|
||||
if n <= 0 {
|
||||
panic("XTUCK: invalid length")
|
||||
|
@ -597,30 +600,30 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.InsertAt(a, n)
|
||||
|
||||
case ROT:
|
||||
case opcode.ROT:
|
||||
e := v.estack.RemoveAt(2)
|
||||
if e == nil {
|
||||
panic("no top-level element found")
|
||||
}
|
||||
v.estack.Push(e)
|
||||
|
||||
case DEPTH:
|
||||
case opcode.DEPTH:
|
||||
v.estack.PushVal(v.estack.Len())
|
||||
|
||||
case NIP:
|
||||
case opcode.NIP:
|
||||
elem := v.estack.RemoveAt(1)
|
||||
if elem == nil {
|
||||
panic("no second element found")
|
||||
}
|
||||
|
||||
case OVER:
|
||||
case opcode.OVER:
|
||||
a := v.estack.Peek(1)
|
||||
if a == nil {
|
||||
panic("no second element found")
|
||||
}
|
||||
v.estack.Push(a)
|
||||
|
||||
case PICK:
|
||||
case opcode.PICK:
|
||||
n := int(v.estack.Pop().BigInt().Int64())
|
||||
if n < 0 {
|
||||
panic("negative stack item returned")
|
||||
|
@ -631,7 +634,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.Push(a)
|
||||
|
||||
case ROLL:
|
||||
case opcode.ROLL:
|
||||
n := int(v.estack.Pop().BigInt().Int64())
|
||||
if n < 0 {
|
||||
panic("negative stack item returned")
|
||||
|
@ -644,13 +647,13 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.estack.Push(e)
|
||||
}
|
||||
|
||||
case DROP:
|
||||
case opcode.DROP:
|
||||
if v.estack.Len() < 1 {
|
||||
panic("stack is too small")
|
||||
}
|
||||
v.estack.Pop()
|
||||
|
||||
case EQUAL:
|
||||
case opcode.EQUAL:
|
||||
b := v.estack.Pop()
|
||||
if b == nil {
|
||||
panic("no top-level element found")
|
||||
|
@ -673,28 +676,28 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.estack.PushVal(reflect.DeepEqual(a, b))
|
||||
|
||||
// Bit operations.
|
||||
case INVERT:
|
||||
case opcode.INVERT:
|
||||
// inplace
|
||||
a := v.estack.Peek(0).BigInt()
|
||||
a.Not(a)
|
||||
|
||||
case AND:
|
||||
case opcode.AND:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(new(big.Int).And(b, a))
|
||||
|
||||
case OR:
|
||||
case opcode.OR:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(new(big.Int).Or(b, a))
|
||||
|
||||
case XOR:
|
||||
case opcode.XOR:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(new(big.Int).Xor(b, a))
|
||||
|
||||
// Numeric operations.
|
||||
case ADD:
|
||||
case opcode.ADD:
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
b := v.estack.Pop().BigInt()
|
||||
|
@ -704,7 +707,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.checkBigIntSize(c)
|
||||
v.estack.PushVal(c)
|
||||
|
||||
case SUB:
|
||||
case opcode.SUB:
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
a := v.estack.Pop().BigInt()
|
||||
|
@ -714,7 +717,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.checkBigIntSize(c)
|
||||
v.estack.PushVal(c)
|
||||
|
||||
case DIV:
|
||||
case opcode.DIV:
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
a := v.estack.Pop().BigInt()
|
||||
|
@ -722,7 +725,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
|
||||
v.estack.PushVal(new(big.Int).Div(a, b))
|
||||
|
||||
case MUL:
|
||||
case opcode.MUL:
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
b := v.estack.Pop().BigInt()
|
||||
|
@ -732,7 +735,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.checkBigIntSize(c)
|
||||
v.estack.PushVal(c)
|
||||
|
||||
case MOD:
|
||||
case opcode.MOD:
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
a := v.estack.Pop().BigInt()
|
||||
|
@ -740,7 +743,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
|
||||
v.estack.PushVal(new(big.Int).Mod(a, b))
|
||||
|
||||
case SHL, SHR:
|
||||
case opcode.SHL, opcode.SHR:
|
||||
b := v.estack.Pop().BigInt().Int64()
|
||||
if b == 0 {
|
||||
return
|
||||
|
@ -751,7 +754,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.checkBigIntSize(a)
|
||||
|
||||
var item big.Int
|
||||
if op == SHL {
|
||||
if op == opcode.SHL {
|
||||
item.Lsh(a, uint(b))
|
||||
} else {
|
||||
item.Rsh(a, uint(b))
|
||||
|
@ -760,47 +763,47 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.checkBigIntSize(&item)
|
||||
v.estack.PushVal(&item)
|
||||
|
||||
case BOOLAND:
|
||||
case opcode.BOOLAND:
|
||||
b := v.estack.Pop().Bool()
|
||||
a := v.estack.Pop().Bool()
|
||||
v.estack.PushVal(a && b)
|
||||
|
||||
case BOOLOR:
|
||||
case opcode.BOOLOR:
|
||||
b := v.estack.Pop().Bool()
|
||||
a := v.estack.Pop().Bool()
|
||||
v.estack.PushVal(a || b)
|
||||
|
||||
case NUMEQUAL:
|
||||
case opcode.NUMEQUAL:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) == 0)
|
||||
|
||||
case NUMNOTEQUAL:
|
||||
case opcode.NUMNOTEQUAL:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) != 0)
|
||||
|
||||
case LT:
|
||||
case opcode.LT:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) == -1)
|
||||
|
||||
case GT:
|
||||
case opcode.GT:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) == 1)
|
||||
|
||||
case LTE:
|
||||
case opcode.LTE:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) <= 0)
|
||||
|
||||
case GTE:
|
||||
case opcode.GTE:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) >= 0)
|
||||
|
||||
case MIN:
|
||||
case opcode.MIN:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
val := a
|
||||
|
@ -809,7 +812,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.PushVal(val)
|
||||
|
||||
case MAX:
|
||||
case opcode.MAX:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
val := a
|
||||
|
@ -818,46 +821,46 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.PushVal(val)
|
||||
|
||||
case WITHIN:
|
||||
case opcode.WITHIN:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(x) <= 0 && x.Cmp(b) == -1)
|
||||
|
||||
case INC:
|
||||
case opcode.INC:
|
||||
x := v.estack.Pop().BigInt()
|
||||
a := new(big.Int).Add(x, big.NewInt(1))
|
||||
v.checkBigIntSize(a)
|
||||
v.estack.PushVal(a)
|
||||
|
||||
case DEC:
|
||||
case opcode.DEC:
|
||||
x := v.estack.Pop().BigInt()
|
||||
a := new(big.Int).Sub(x, big.NewInt(1))
|
||||
v.checkBigIntSize(a)
|
||||
v.estack.PushVal(a)
|
||||
|
||||
case SIGN:
|
||||
case opcode.SIGN:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Sign())
|
||||
|
||||
case NEGATE:
|
||||
case opcode.NEGATE:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Neg(x))
|
||||
|
||||
case ABS:
|
||||
case opcode.ABS:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Abs(x))
|
||||
|
||||
case NOT:
|
||||
case opcode.NOT:
|
||||
x := v.estack.Pop().Bool()
|
||||
v.estack.PushVal(!x)
|
||||
|
||||
case NZ:
|
||||
case opcode.NZ:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Cmp(big.NewInt(0)) != 0)
|
||||
|
||||
// Object operations.
|
||||
case NEWARRAY:
|
||||
case opcode.NEWARRAY:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *StructItem:
|
||||
|
@ -875,7 +878,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.estack.PushVal(&ArrayItem{items})
|
||||
}
|
||||
|
||||
case NEWSTRUCT:
|
||||
case opcode.NEWSTRUCT:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *ArrayItem:
|
||||
|
@ -893,7 +896,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.estack.PushVal(&StructItem{items})
|
||||
}
|
||||
|
||||
case APPEND:
|
||||
case opcode.APPEND:
|
||||
itemElem := v.estack.Pop()
|
||||
arrElem := v.estack.Pop()
|
||||
|
||||
|
@ -920,7 +923,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
|
||||
v.estack.updateSizeAdd(val)
|
||||
|
||||
case PACK:
|
||||
case opcode.PACK:
|
||||
n := int(v.estack.Pop().BigInt().Int64())
|
||||
if n < 0 || n > v.estack.Len() || n > MaxArraySize {
|
||||
panic("OPACK: invalid length")
|
||||
|
@ -933,7 +936,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
|
||||
v.estack.PushVal(items)
|
||||
|
||||
case UNPACK:
|
||||
case opcode.UNPACK:
|
||||
a := v.estack.Pop().Array()
|
||||
l := len(a)
|
||||
for i := l - 1; i >= 0; i-- {
|
||||
|
@ -941,7 +944,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.PushVal(l)
|
||||
|
||||
case PICKITEM:
|
||||
case opcode.PICKITEM:
|
||||
key := v.estack.Pop()
|
||||
validateMapKey(key)
|
||||
|
||||
|
@ -972,7 +975,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.estack.PushVal(int(item))
|
||||
}
|
||||
|
||||
case SETITEM:
|
||||
case opcode.SETITEM:
|
||||
item := v.estack.Pop().value
|
||||
key := v.estack.Pop()
|
||||
validateMapKey(key)
|
||||
|
@ -1003,14 +1006,14 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
panic(fmt.Sprintf("SETITEM: invalid item type %s", t))
|
||||
}
|
||||
|
||||
case REVERSE:
|
||||
case opcode.REVERSE:
|
||||
a := v.estack.Pop().Array()
|
||||
if len(a) > 1 {
|
||||
for i, j := 0, len(a)-1; i <= j; i, j = i+1, j-1 {
|
||||
a[i], a[j] = a[j], a[i]
|
||||
}
|
||||
}
|
||||
case REMOVE:
|
||||
case opcode.REMOVE:
|
||||
key := v.estack.Pop()
|
||||
validateMapKey(key)
|
||||
|
||||
|
@ -1043,7 +1046,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
panic("REMOVE: invalid type")
|
||||
}
|
||||
|
||||
case ARRAYSIZE:
|
||||
case opcode.ARRAYSIZE:
|
||||
elem := v.estack.Pop()
|
||||
// Cause there is no native (byte) item type here, hence we need to check
|
||||
// the type of the item for array size operations.
|
||||
|
@ -1056,12 +1059,12 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.estack.PushVal(len(elem.Bytes()))
|
||||
}
|
||||
|
||||
case SIZE:
|
||||
case opcode.SIZE:
|
||||
elem := v.estack.Pop()
|
||||
arr := elem.Bytes()
|
||||
v.estack.PushVal(len(arr))
|
||||
|
||||
case JMP, JMPIF, JMPIFNOT:
|
||||
case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT:
|
||||
var (
|
||||
rOffset = int16(binary.LittleEndian.Uint16(parameter))
|
||||
offset = ctx.ip + int(rOffset)
|
||||
|
@ -1070,9 +1073,9 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
panic(fmt.Sprintf("JMP: invalid offset %d ip at %d", offset, ctx.ip))
|
||||
}
|
||||
cond := true
|
||||
if op > JMP {
|
||||
if op > opcode.JMP {
|
||||
cond = v.estack.Pop().Bool()
|
||||
if op == JMPIFNOT {
|
||||
if op == opcode.JMPIFNOT {
|
||||
cond = !cond
|
||||
}
|
||||
}
|
||||
|
@ -1080,18 +1083,18 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
ctx.nextip = offset
|
||||
}
|
||||
|
||||
case CALL:
|
||||
case opcode.CALL:
|
||||
v.checkInvocationStackSize()
|
||||
|
||||
newCtx := ctx.Copy()
|
||||
newCtx.rvcount = -1
|
||||
v.istack.PushVal(newCtx)
|
||||
err = v.execute(v.Context(), JMP, parameter)
|
||||
err = v.execute(v.Context(), opcode.JMP, parameter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
case SYSCALL:
|
||||
case opcode.SYSCALL:
|
||||
ifunc, ok := v.interop[string(parameter)]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("interop hook (%q) not registered", parameter))
|
||||
|
@ -1100,12 +1103,12 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
panic(fmt.Sprintf("failed to invoke syscall: %s", err))
|
||||
}
|
||||
|
||||
case APPCALL, TAILCALL:
|
||||
case opcode.APPCALL, opcode.TAILCALL:
|
||||
if v.getScript == nil {
|
||||
panic("no getScript callback is set up")
|
||||
}
|
||||
|
||||
if op == APPCALL {
|
||||
if op == opcode.APPCALL {
|
||||
v.checkInvocationStackSize()
|
||||
}
|
||||
|
||||
|
@ -1119,13 +1122,13 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
panic("could not find script")
|
||||
}
|
||||
|
||||
if op == TAILCALL {
|
||||
if op == opcode.TAILCALL {
|
||||
_ = v.istack.Pop()
|
||||
}
|
||||
|
||||
v.LoadScript(script)
|
||||
|
||||
case RET:
|
||||
case opcode.RET:
|
||||
oldCtx := v.istack.Pop().Value().(*Context)
|
||||
rvcount := oldCtx.rvcount
|
||||
oldEstack := v.estack
|
||||
|
@ -1151,12 +1154,12 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.astack = v.Context().astack
|
||||
}
|
||||
|
||||
case CHECKSIG, VERIFY:
|
||||
case opcode.CHECKSIG, opcode.VERIFY:
|
||||
var hashToCheck []byte
|
||||
|
||||
keyb := v.estack.Pop().Bytes()
|
||||
signature := v.estack.Pop().Bytes()
|
||||
if op == CHECKSIG {
|
||||
if op == opcode.CHECKSIG {
|
||||
if v.checkhash == nil {
|
||||
panic("VM is not set up properly for signature checks")
|
||||
}
|
||||
|
@ -1173,7 +1176,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
res := pkey.Verify(signature, hashToCheck)
|
||||
v.estack.PushVal(res)
|
||||
|
||||
case CHECKMULTISIG:
|
||||
case opcode.CHECKMULTISIG:
|
||||
pkeys, err := v.estack.popSigElements()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("wrong parameters: %s", err.Error()))
|
||||
|
@ -1214,10 +1217,10 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.PushVal(sigok)
|
||||
|
||||
case NEWMAP:
|
||||
case opcode.NEWMAP:
|
||||
v.estack.Push(&Element{value: NewMapItem()})
|
||||
|
||||
case KEYS:
|
||||
case opcode.KEYS:
|
||||
item := v.estack.Pop()
|
||||
if item == nil {
|
||||
panic("no argument")
|
||||
|
@ -1234,7 +1237,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
v.estack.PushVal(arr)
|
||||
|
||||
case VALUES:
|
||||
case opcode.VALUES:
|
||||
item := v.estack.Pop()
|
||||
if item == nil {
|
||||
panic("no argument")
|
||||
|
@ -1259,7 +1262,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
|
||||
v.estack.PushVal(arr)
|
||||
|
||||
case HASKEY:
|
||||
case opcode.HASKEY:
|
||||
key := v.estack.Pop()
|
||||
validateMapKey(key)
|
||||
|
||||
|
@ -1281,31 +1284,31 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
}
|
||||
|
||||
// Cryptographic operations.
|
||||
case SHA1:
|
||||
case opcode.SHA1:
|
||||
b := v.estack.Pop().Bytes()
|
||||
sha := sha1.New()
|
||||
sha.Write(b)
|
||||
v.estack.PushVal(sha.Sum(nil))
|
||||
|
||||
case SHA256:
|
||||
case opcode.SHA256:
|
||||
b := v.estack.Pop().Bytes()
|
||||
v.estack.PushVal(hash.Sha256(b).Bytes())
|
||||
|
||||
case HASH160:
|
||||
case opcode.HASH160:
|
||||
b := v.estack.Pop().Bytes()
|
||||
v.estack.PushVal(hash.Hash160(b).Bytes())
|
||||
|
||||
case HASH256:
|
||||
case opcode.HASH256:
|
||||
b := v.estack.Pop().Bytes()
|
||||
v.estack.PushVal(hash.DoubleSha256(b).Bytes())
|
||||
|
||||
case NOP:
|
||||
case opcode.NOP:
|
||||
// unlucky ^^
|
||||
|
||||
case CALLI, CALLE, CALLED, CALLET, CALLEDT:
|
||||
case opcode.CALLI, opcode.CALLE, opcode.CALLED, opcode.CALLET, opcode.CALLEDT:
|
||||
var (
|
||||
tailCall = (op == CALLET || op == CALLEDT)
|
||||
hashOnStack = (op == CALLED || op == CALLEDT)
|
||||
tailCall = (op == opcode.CALLET || op == opcode.CALLEDT)
|
||||
hashOnStack = (op == opcode.CALLED || op == opcode.CALLEDT)
|
||||
addElement int
|
||||
newCtx *Context
|
||||
)
|
||||
|
@ -1327,7 +1330,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.checkInvocationStackSize()
|
||||
}
|
||||
|
||||
if op == CALLI {
|
||||
if op == opcode.CALLI {
|
||||
newCtx = ctx.Copy()
|
||||
} else {
|
||||
var hashBytes []byte
|
||||
|
@ -1362,17 +1365,17 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) (err error)
|
|||
v.istack.PushVal(newCtx)
|
||||
v.estack = newCtx.estack
|
||||
v.astack = newCtx.astack
|
||||
if op == CALLI {
|
||||
err = v.execute(v.Context(), JMP, parameter[2:])
|
||||
if op == opcode.CALLI {
|
||||
err = v.execute(v.Context(), opcode.JMP, parameter[2:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
case THROW:
|
||||
case opcode.THROW:
|
||||
panic("THROW")
|
||||
|
||||
case THROWIFNOT:
|
||||
case opcode.THROWIFNOT:
|
||||
if !v.estack.Pop().Bool() {
|
||||
panic("THROWIFNOT")
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue