From 8d4dd2d2e1034f47433da786a03f8ccfa792d53d Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 3 Dec 2019 17:05:06 +0300 Subject: [PATCH 1/5] 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. --- pkg/consensus/consensus.go | 4 +- pkg/consensus/payload.go | 3 +- pkg/core/util.go | 10 +- pkg/rpc/txBuilder.go | 3 +- pkg/smartcontract/contract.go | 5 +- pkg/smartcontract/contract_test.go | 8 +- pkg/vm/compiler/codegen.go | 162 ++++----- pkg/vm/compiler/emit.go | 36 +- pkg/vm/context.go | 27 +- pkg/vm/contract_checks.go | 28 +- pkg/vm/contract_checks_test.go | 191 +++++----- pkg/vm/emit.go | 39 +- pkg/vm/emit_test.go | 13 +- pkg/vm/instruction_string.go | 393 -------------------- pkg/vm/instructions.go | 215 ----------- pkg/vm/json_test.go | 3 +- pkg/vm/opcode/opcode.go | 215 +++++++++++ pkg/vm/opcode/opcode_string.go | 393 ++++++++++++++++++++ pkg/vm/opcode/opcode_test.go | 20 ++ pkg/vm/vm.go | 211 +++++------ pkg/vm/vm_test.go | 554 +++++++++++++++-------------- 21 files changed, 1285 insertions(+), 1248 deletions(-) delete mode 100644 pkg/vm/instruction_string.go delete mode 100644 pkg/vm/instructions.go create mode 100644 pkg/vm/opcode/opcode.go create mode 100644 pkg/vm/opcode/opcode_string.go create mode 100644 pkg/vm/opcode/opcode_test.go diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 61f7fea11..c404561d0 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -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++ } diff --git a/pkg/consensus/payload.go b/pkg/consensus/payload.go index 881d0bbf1..e80f4bb79 100644 --- a/pkg/consensus/payload.go +++ b/pkg/consensus/payload.go @@ -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 diff --git a/pkg/core/util.go b/pkg/core/util.go index db97c7f86..05ba10bdd 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -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\"}]", diff --git a/pkg/rpc/txBuilder.go b/pkg/rpc/txBuilder.go index d9519d5fc..bd79511ef 100644 --- a/pkg/rpc/txBuilder.go +++ b/pkg/rpc/txBuilder.go @@ -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 } diff --git a/pkg/smartcontract/contract.go b/pkg/smartcontract/contract.go index e51e356cb..123971d32 100644 --- a/pkg/smartcontract/contract.go +++ b/pkg/smartcontract/contract.go @@ -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 } diff --git a/pkg/smartcontract/contract_test.go b/pkg/smartcontract/contract_test.go index d011aa1b7..3f9667e16 100644 --- a/pkg/smartcontract/contract_test.go +++ b/pkg/smartcontract/contract_test.go @@ -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)) } diff --git a/pkg/vm/compiler/codegen.go b/pkg/vm/compiler/codegen.go index c850b8dbc..45c9dde69 100644 --- a/pkg/vm/compiler/codegen.go +++ b/pkg/vm/compiler/codegen.go @@ -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 diff --git a/pkg/vm/compiler/emit.go b/pkg/vm/compiler/emit.go index 6e1834e5a..a73b59475 100644 --- a/pkg/vm/compiler/emit.go +++ b/pkg/vm/compiler/emit.go @@ -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 diff --git a/pkg/vm/context.go b/pkg/vm/context.go index cefb183dd..413fc1c3c 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -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. diff --git a/pkg/vm/contract_checks.go b/pkg/vm/contract_checks.go index f51e7c99b..375c3ceec 100644 --- a/pkg/vm/contract_checks.go +++ b/pkg/vm/contract_checks.go @@ -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 diff --git a/pkg/vm/contract_checks_test.go b/pkg/vm/contract_checks_test.go index 791912822..bafeaff67 100644 --- a/pkg/vm/contract_checks_test.go +++ b/pkg/vm/contract_checks_test.go @@ -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)) } diff --git a/pkg/vm/emit.go b/pkg/vm/emit.go index db76fc238..f9c2f4a78 100644 --- a/pkg/vm/emit.go +++ b/pkg/vm/emit.go @@ -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 diff --git a/pkg/vm/emit_test.go b/pkg/vm/emit_test.go index 0baf995bc..1278f3d7b 100644 --- a/pkg/vm/emit_test.go +++ b/pkg/vm/emit_test.go @@ -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)) } diff --git a/pkg/vm/instruction_string.go b/pkg/vm/instruction_string.go deleted file mode 100644 index 9e463de49..000000000 --- a/pkg/vm/instruction_string.go +++ /dev/null @@ -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) + ")" -} diff --git a/pkg/vm/instructions.go b/pkg/vm/instructions.go deleted file mode 100644 index bfbc8221e..000000000 --- a/pkg/vm/instructions.go +++ /dev/null @@ -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 -) diff --git a/pkg/vm/json_test.go b/pkg/vm/json_test.go index d0050e6c7..bafbc2f41 100644 --- a/pkg/vm/json_test.go +++ b/pkg/vm/json_test.go @@ -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) diff --git a/pkg/vm/opcode/opcode.go b/pkg/vm/opcode/opcode.go new file mode 100644 index 000000000..f3e09a5a8 --- /dev/null +++ b/pkg/vm/opcode/opcode.go @@ -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 +) diff --git a/pkg/vm/opcode/opcode_string.go b/pkg/vm/opcode/opcode_string.go new file mode 100644 index 000000000..7a7ed4cb9 --- /dev/null +++ b/pkg/vm/opcode/opcode_string.go @@ -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) + ")" +} diff --git a/pkg/vm/opcode/opcode_test.go b/pkg/vm/opcode/opcode_test.go new file mode 100644 index 000000000..256d13137 --- /dev/null +++ b/pkg/vm/opcode/opcode_test.go @@ -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()) + } +} diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 2c131c772..9eb83f209 100644 --- a/pkg/vm/vm.go +++ b/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") } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 2a254aabe..7f89eb6e7 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -11,6 +11,7 @@ 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/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -24,7 +25,7 @@ func TestInteropHook(t *testing.T) { buf := new(bytes.Buffer) EmitSyscall(buf, "foo") - EmitOpcode(buf, RET) + EmitOpcode(buf, opcode.RET) v.Load(buf.Bytes()) runVM(t, v) assert.Equal(t, 1, v.estack.Len()) @@ -56,7 +57,7 @@ func TestPushBytes1to75(t *testing.T) { assert.IsType(t, elem.Bytes(), b) assert.Equal(t, 0, vm.estack.Len()) - errExec := vm.execute(nil, RET, nil) + errExec := vm.execute(nil, opcode.RET, nil) require.NoError(t, errExec) assert.Equal(t, 0, vm.astack.Len()) @@ -67,7 +68,7 @@ func TestPushBytes1to75(t *testing.T) { func TestPushBytesNoParam(t *testing.T) { prog := make([]byte, 1) - prog[0] = byte(PUSHBYTES1) + prog[0] = byte(opcode.PUSHBYTES1) vm := load(prog) checkVMFailed(t, vm) } @@ -87,10 +88,10 @@ func checkVMFailed(t *testing.T, vm *VM) { func TestStackLimitPUSH1Good(t *testing.T) { prog := make([]byte, MaxStackSize*2) for i := 0; i < MaxStackSize; i++ { - prog[i] = byte(PUSH1) + prog[i] = byte(opcode.PUSH1) } for i := MaxStackSize; i < MaxStackSize*2; i++ { - prog[i] = byte(DROP) + prog[i] = byte(opcode.DROP) } v := load(prog) @@ -100,7 +101,7 @@ func TestStackLimitPUSH1Good(t *testing.T) { func TestStackLimitPUSH1Bad(t *testing.T) { prog := make([]byte, MaxStackSize+1) for i := range prog { - prog[i] = byte(PUSH1) + prog[i] = byte(opcode.PUSH1) } v := load(prog) checkVMFailed(t, v) @@ -114,20 +115,20 @@ func TestStackLimitPUSH1Bad(t *testing.T) { // - struct (size+1) // - array (1) of struct (size+1) // which equals to size*2+3 elements in total. -func appendBigStruct(size uint16) []Instruction { - prog := make([]Instruction, size*2) +func appendBigStruct(size uint16) []opcode.Opcode { + prog := make([]opcode.Opcode, size*2) for i := uint16(0); i < size; i++ { - prog[i*2] = PUSH0 - prog[i*2+1] = NEWSTRUCT + prog[i*2] = opcode.PUSH0 + prog[i*2+1] = opcode.NEWSTRUCT } return append(prog, - PUSHBYTES2, Instruction(size), Instruction(size>>8), // LE - PACK, NEWSTRUCT, - DUP, - PUSH0, NEWARRAY, TOALTSTACK, DUPFROMALTSTACK, - SWAP, - APPEND, RET) + opcode.PUSHBYTES2, opcode.Opcode(size), opcode.Opcode(size>>8), // LE + opcode.PACK, opcode.NEWSTRUCT, + opcode.DUP, + opcode.PUSH0, opcode.NEWARRAY, opcode.TOALTSTACK, opcode.DUPFROMALTSTACK, + opcode.SWAP, + opcode.APPEND, opcode.RET) } func TestStackLimitAPPENDStructGood(t *testing.T) { @@ -144,30 +145,30 @@ func TestStackLimitAPPENDStructBad(t *testing.T) { func TestStackLimit(t *testing.T) { expected := []struct { - inst Instruction + inst opcode.Opcode size int }{ - {PUSH2, 1}, - {NEWARRAY, 3}, // array + 2 items - {TOALTSTACK, 3}, - {DUPFROMALTSTACK, 4}, - {NEWSTRUCT, 6}, // all items are copied - {NEWMAP, 7}, - {DUP, 8}, - {PUSH2, 9}, - {DUPFROMALTSTACK, 10}, - {SETITEM, 8}, // -3 items and 1 new element in map - {DUP, 9}, - {PUSH2, 10}, - {DUPFROMALTSTACK, 11}, - {SETITEM, 8}, // -3 items and no new elements in map - {DUP, 9}, - {PUSH2, 10}, - {REMOVE, 7}, // as we have right after NEWMAP - {DROP, 6}, // DROP map with no elements + {opcode.PUSH2, 1}, + {opcode.NEWARRAY, 3}, // array + 2 items + {opcode.TOALTSTACK, 3}, + {opcode.DUPFROMALTSTACK, 4}, + {opcode.NEWSTRUCT, 6}, // all items are copied + {opcode.NEWMAP, 7}, + {opcode.DUP, 8}, + {opcode.PUSH2, 9}, + {opcode.DUPFROMALTSTACK, 10}, + {opcode.SETITEM, 8}, // -3 items and 1 new element in map + {opcode.DUP, 9}, + {opcode.PUSH2, 10}, + {opcode.DUPFROMALTSTACK, 11}, + {opcode.SETITEM, 8}, // -3 items and no new elements in map + {opcode.DUP, 9}, + {opcode.PUSH2, 10}, + {opcode.REMOVE, 7}, // as we have right after NEWMAP + {opcode.DROP, 6}, // DROP map with no elements } - prog := make([]Instruction, len(expected)) + prog := make([]opcode.Opcode, len(expected)) for i := range expected { prog[i] = expected[i].inst } @@ -181,14 +182,14 @@ func TestStackLimit(t *testing.T) { func TestPushBytesShort(t *testing.T) { prog := make([]byte, 10) - prog[0] = byte(PUSHBYTES10) // but only 9 left in the `prog` + prog[0] = byte(opcode.PUSHBYTES10) // but only 9 left in the `prog` vm := load(prog) checkVMFailed(t, vm) } func TestPushm1to16(t *testing.T) { var prog []byte - for i := int(PUSHM1); i <= int(PUSH16); i++ { + for i := int(opcode.PUSHM1); i <= int(opcode.PUSH16); i++ { if i == 80 { continue // opcode layout we got here. } @@ -196,7 +197,7 @@ func TestPushm1to16(t *testing.T) { } vm := load(prog) - for i := int(PUSHM1); i <= int(PUSH16); i++ { + for i := int(opcode.PUSHM1); i <= int(opcode.PUSH16); i++ { if i == 80 { continue // nice opcode layout we got here. } @@ -205,25 +206,25 @@ func TestPushm1to16(t *testing.T) { elem := vm.estack.Pop() assert.IsType(t, &BigIntegerItem{}, elem.value) - val := i - int(PUSH1) + 1 + val := i - int(opcode.PUSH1) + 1 assert.Equal(t, elem.BigInt().Int64(), int64(val)) } } func TestPushData1BadNoN(t *testing.T) { - prog := []byte{byte(PUSHDATA1)} + prog := []byte{byte(opcode.PUSHDATA1)} vm := load(prog) checkVMFailed(t, vm) } func TestPushData1BadN(t *testing.T) { - prog := []byte{byte(PUSHDATA1), 1} + prog := []byte{byte(opcode.PUSHDATA1), 1} vm := load(prog) checkVMFailed(t, vm) } func TestPushData1Good(t *testing.T) { - prog := makeProgram(PUSHDATA1, 3, 1, 2, 3) + prog := makeProgram(opcode.PUSHDATA1, 3, 1, 2, 3) vm := load(prog) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) @@ -231,25 +232,25 @@ func TestPushData1Good(t *testing.T) { } func TestPushData2BadNoN(t *testing.T) { - prog := []byte{byte(PUSHDATA2)} + prog := []byte{byte(opcode.PUSHDATA2)} vm := load(prog) checkVMFailed(t, vm) } func TestPushData2ShortN(t *testing.T) { - prog := []byte{byte(PUSHDATA2), 0} + prog := []byte{byte(opcode.PUSHDATA2), 0} vm := load(prog) checkVMFailed(t, vm) } func TestPushData2BadN(t *testing.T) { - prog := []byte{byte(PUSHDATA2), 1, 0} + prog := []byte{byte(opcode.PUSHDATA2), 1, 0} vm := load(prog) checkVMFailed(t, vm) } func TestPushData2Good(t *testing.T) { - prog := makeProgram(PUSHDATA2, 3, 0, 1, 2, 3) + prog := makeProgram(opcode.PUSHDATA2, 3, 0, 1, 2, 3) vm := load(prog) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) @@ -257,26 +258,26 @@ func TestPushData2Good(t *testing.T) { } func TestPushData4BadNoN(t *testing.T) { - prog := []byte{byte(PUSHDATA4)} + prog := []byte{byte(opcode.PUSHDATA4)} vm := load(prog) checkVMFailed(t, vm) } func TestPushData4BadN(t *testing.T) { - prog := []byte{byte(PUSHDATA4), 1, 0, 0, 0} + prog := []byte{byte(opcode.PUSHDATA4), 1, 0, 0, 0} vm := load(prog) checkVMFailed(t, vm) } func TestPushData4ShortN(t *testing.T) { - prog := []byte{byte(PUSHDATA4), 0, 0, 0} + prog := []byte{byte(opcode.PUSHDATA4), 0, 0, 0} vm := load(prog) checkVMFailed(t, vm) } func TestPushData4BigN(t *testing.T) { prog := make([]byte, 1+4+MaxItemSize+1) - prog[0] = byte(PUSHDATA4) + prog[0] = byte(opcode.PUSHDATA4) binary.LittleEndian.PutUint32(prog[1:], MaxItemSize+1) vm := load(prog) @@ -285,7 +286,7 @@ func TestPushData4BigN(t *testing.T) { } func TestPushData4Good(t *testing.T) { - prog := makeProgram(PUSHDATA4, 3, 0, 0, 0, 1, 2, 3) + prog := makeProgram(opcode.PUSHDATA4, 3, 0, 0, 0, 1, 2, 3) vm := load(prog) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) @@ -293,7 +294,7 @@ func TestPushData4Good(t *testing.T) { } func getSyscallProg(name string) (prog []byte) { - prog = []byte{byte(SYSCALL)} + prog = []byte{byte(opcode.SYSCALL)} prog = append(prog, byte(len(name))) prog = append(prog, name...) @@ -303,7 +304,7 @@ func getSyscallProg(name string) (prog []byte) { func getSerializeProg() (prog []byte) { prog = append(prog, getSyscallProg("Neo.Runtime.Serialize")...) prog = append(prog, getSyscallProg("Neo.Runtime.Deserialize")...) - prog = append(prog, byte(RET)) + prog = append(prog, byte(opcode.RET)) return } @@ -381,9 +382,9 @@ func TestSerializeArrayBad(t *testing.T) { func TestSerializeDupInteger(t *testing.T) { prog := []byte{ - byte(PUSH0), byte(NEWARRAY), - byte(DUP), byte(PUSH2), byte(DUP), byte(TOALTSTACK), byte(APPEND), - byte(DUP), byte(FROMALTSTACK), byte(APPEND), + byte(opcode.PUSH0), byte(opcode.NEWARRAY), + byte(opcode.DUP), byte(opcode.PUSH2), byte(opcode.DUP), byte(opcode.TOALTSTACK), byte(opcode.APPEND), + byte(opcode.DUP), byte(opcode.FROMALTSTACK), byte(opcode.APPEND), } vm := load(append(prog, getSerializeProg()...)) @@ -407,7 +408,7 @@ func TestSerializeStruct(t *testing.T) { } func TestDeserializeUnknown(t *testing.T) { - prog := append(getSyscallProg("Neo.Runtime.Deserialize"), byte(RET)) + prog := append(getSyscallProg("Neo.Runtime.Deserialize"), byte(opcode.RET)) vm := load(prog) data, err := serializeItem(NewBigIntegerItem(123)) @@ -446,11 +447,11 @@ func TestSerializeInterop(t *testing.T) { func callNTimes(n uint16) []byte { return makeProgram( - PUSHBYTES2, Instruction(n), Instruction(n>>8), // little-endian - TOALTSTACK, DUPFROMALTSTACK, - JMPIF, 0x4, 0, RET, - FROMALTSTACK, DEC, - CALL, 0xF8, 0xFF) // -8 -> JMP to TOALTSTACK) + opcode.PUSHBYTES2, opcode.Opcode(n), opcode.Opcode(n>>8), // little-endian + opcode.TOALTSTACK, opcode.DUPFROMALTSTACK, + opcode.JMPIF, 0x4, 0, opcode.RET, + opcode.FROMALTSTACK, opcode.DEC, + opcode.CALL, 0xF8, 0xFF) // -8 -> JMP to TOALTSTACK) } func TestInvocationLimitGood(t *testing.T) { @@ -466,13 +467,13 @@ func TestInvocationLimitBad(t *testing.T) { } func TestNOTNoArgument(t *testing.T) { - prog := makeProgram(NOT) + prog := makeProgram(opcode.NOT) vm := load(prog) checkVMFailed(t, vm) } func TestNOTBool(t *testing.T) { - prog := makeProgram(NOT) + prog := makeProgram(opcode.NOT) vm := load(prog) vm.estack.PushVal(false) runVM(t, vm) @@ -480,7 +481,7 @@ func TestNOTBool(t *testing.T) { } func TestNOTNonZeroInt(t *testing.T) { - prog := makeProgram(NOT) + prog := makeProgram(opcode.NOT) vm := load(prog) vm.estack.PushVal(3) runVM(t, vm) @@ -488,7 +489,7 @@ func TestNOTNonZeroInt(t *testing.T) { } func TestNOTArray(t *testing.T) { - prog := makeProgram(NOT) + prog := makeProgram(opcode.NOT) vm := load(prog) vm.estack.PushVal([]StackItem{}) runVM(t, vm) @@ -496,7 +497,7 @@ func TestNOTArray(t *testing.T) { } func TestNOTStruct(t *testing.T) { - prog := makeProgram(NOT) + prog := makeProgram(opcode.NOT) vm := load(prog) vm.estack.Push(NewElement(&StructItem{[]StackItem{}})) runVM(t, vm) @@ -504,7 +505,7 @@ func TestNOTStruct(t *testing.T) { } func TestNOTByteArray0(t *testing.T) { - prog := makeProgram(NOT) + prog := makeProgram(opcode.NOT) vm := load(prog) vm.estack.PushVal([]byte{0, 0}) runVM(t, vm) @@ -512,7 +513,7 @@ func TestNOTByteArray0(t *testing.T) { } func TestNOTByteArray1(t *testing.T) { - prog := makeProgram(NOT) + prog := makeProgram(opcode.NOT) vm := load(prog) vm.estack.PushVal([]byte{0, 1}) runVM(t, vm) @@ -527,7 +528,7 @@ func getBigInt(a, b int64) *big.Int { } func TestAdd(t *testing.T) { - prog := makeProgram(ADD) + prog := makeProgram(opcode.ADD) vm := load(prog) vm.estack.PushVal(4) vm.estack.PushVal(2) @@ -536,14 +537,14 @@ func TestAdd(t *testing.T) { } func TestADDBigResult(t *testing.T) { - prog := makeProgram(ADD) + prog := makeProgram(opcode.ADD) vm := load(prog) vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, -1)) vm.estack.PushVal(1) checkVMFailed(t, vm) } -func testBigArgument(t *testing.T, inst Instruction) { +func testBigArgument(t *testing.T, inst opcode.Opcode) { prog := makeProgram(inst) x := getBigInt(MaxBigIntegerSizeBits, 0) t.Run(inst.String()+" big 1-st argument", func(t *testing.T) { @@ -561,15 +562,15 @@ func testBigArgument(t *testing.T, inst Instruction) { } func TestArithBigArgument(t *testing.T) { - testBigArgument(t, ADD) - testBigArgument(t, SUB) - testBigArgument(t, MUL) - testBigArgument(t, DIV) - testBigArgument(t, MOD) + testBigArgument(t, opcode.ADD) + testBigArgument(t, opcode.SUB) + testBigArgument(t, opcode.MUL) + testBigArgument(t, opcode.DIV) + testBigArgument(t, opcode.MOD) } func TestMul(t *testing.T) { - prog := makeProgram(MUL) + prog := makeProgram(opcode.MUL) vm := load(prog) vm.estack.PushVal(4) vm.estack.PushVal(2) @@ -578,7 +579,7 @@ func TestMul(t *testing.T) { } func TestMULBigResult(t *testing.T) { - prog := makeProgram(MUL) + prog := makeProgram(opcode.MUL) vm := load(prog) vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits/2+1, 0)) vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits/2+1, 0)) @@ -586,7 +587,7 @@ func TestMULBigResult(t *testing.T) { } func TestDiv(t *testing.T) { - prog := makeProgram(DIV) + prog := makeProgram(opcode.DIV) vm := load(prog) vm.estack.PushVal(4) vm.estack.PushVal(2) @@ -595,7 +596,7 @@ func TestDiv(t *testing.T) { } func TestSub(t *testing.T) { - prog := makeProgram(SUB) + prog := makeProgram(opcode.SUB) vm := load(prog) vm.estack.PushVal(4) vm.estack.PushVal(2) @@ -604,7 +605,7 @@ func TestSub(t *testing.T) { } func TestSUBBigResult(t *testing.T) { - prog := makeProgram(SUB) + prog := makeProgram(opcode.SUB) vm := load(prog) vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, -1)) vm.estack.PushVal(-1) @@ -612,7 +613,7 @@ func TestSUBBigResult(t *testing.T) { } func TestSHRGood(t *testing.T) { - prog := makeProgram(SHR) + prog := makeProgram(opcode.SHR) vm := load(prog) vm.estack.PushVal(4) vm.estack.PushVal(2) @@ -622,7 +623,7 @@ func TestSHRGood(t *testing.T) { } func TestSHRZero(t *testing.T) { - prog := makeProgram(SHR) + prog := makeProgram(opcode.SHR) vm := load(prog) vm.estack.PushVal([]byte{0, 1}) vm.estack.PushVal(0) @@ -632,7 +633,7 @@ func TestSHRZero(t *testing.T) { } func TestSHRSmallValue(t *testing.T) { - prog := makeProgram(SHR) + prog := makeProgram(opcode.SHR) vm := load(prog) vm.estack.PushVal(5) vm.estack.PushVal(minSHLArg - 1) @@ -640,7 +641,7 @@ func TestSHRSmallValue(t *testing.T) { } func TestSHRBigArgument(t *testing.T) { - prog := makeProgram(SHR) + prog := makeProgram(opcode.SHR) vm := load(prog) vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, 0)) vm.estack.PushVal(1) @@ -648,7 +649,7 @@ func TestSHRBigArgument(t *testing.T) { } func TestSHLGood(t *testing.T) { - prog := makeProgram(SHL) + prog := makeProgram(opcode.SHL) vm := load(prog) vm.estack.PushVal(4) vm.estack.PushVal(2) @@ -658,7 +659,7 @@ func TestSHLGood(t *testing.T) { } func TestSHLZero(t *testing.T) { - prog := makeProgram(SHL) + prog := makeProgram(opcode.SHL) vm := load(prog) vm.estack.PushVal([]byte{0, 1}) vm.estack.PushVal(0) @@ -668,7 +669,7 @@ func TestSHLZero(t *testing.T) { } func TestSHLBigValue(t *testing.T) { - prog := makeProgram(SHL) + prog := makeProgram(opcode.SHL) vm := load(prog) vm.estack.PushVal(5) vm.estack.PushVal(maxSHLArg + 1) @@ -676,7 +677,7 @@ func TestSHLBigValue(t *testing.T) { } func TestSHLBigResult(t *testing.T) { - prog := makeProgram(SHL) + prog := makeProgram(opcode.SHL) vm := load(prog) vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits/2, 0)) vm.estack.PushVal(MaxBigIntegerSizeBits / 2) @@ -684,7 +685,7 @@ func TestSHLBigResult(t *testing.T) { } func TestSHLBigArgument(t *testing.T) { - prog := makeProgram(SHR) + prog := makeProgram(opcode.SHR) vm := load(prog) vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, 0)) vm.estack.PushVal(1) @@ -692,7 +693,7 @@ func TestSHLBigArgument(t *testing.T) { } func TestLT(t *testing.T) { - prog := makeProgram(LT) + prog := makeProgram(opcode.LT) vm := load(prog) vm.estack.PushVal(4) vm.estack.PushVal(3) @@ -701,7 +702,7 @@ func TestLT(t *testing.T) { } func TestLTE(t *testing.T) { - prog := makeProgram(LTE) + prog := makeProgram(opcode.LTE) vm := load(prog) vm.estack.PushVal(2) vm.estack.PushVal(3) @@ -710,7 +711,7 @@ func TestLTE(t *testing.T) { } func TestGT(t *testing.T) { - prog := makeProgram(GT) + prog := makeProgram(opcode.GT) vm := load(prog) vm.estack.PushVal(9) vm.estack.PushVal(3) @@ -720,7 +721,7 @@ func TestGT(t *testing.T) { } func TestGTE(t *testing.T) { - prog := makeProgram(GTE) + prog := makeProgram(opcode.GTE) vm := load(prog) vm.estack.PushVal(3) vm.estack.PushVal(3) @@ -729,7 +730,7 @@ func TestGTE(t *testing.T) { } func TestDepth(t *testing.T) { - prog := makeProgram(DEPTH) + prog := makeProgram(opcode.DEPTH) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -739,20 +740,20 @@ func TestDepth(t *testing.T) { } func TestEQUALNoArguments(t *testing.T) { - prog := makeProgram(EQUAL) + prog := makeProgram(opcode.EQUAL) vm := load(prog) checkVMFailed(t, vm) } func TestEQUALBad1Argument(t *testing.T) { - prog := makeProgram(EQUAL) + prog := makeProgram(opcode.EQUAL) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestEQUALGoodInteger(t *testing.T) { - prog := makeProgram(EQUAL) + prog := makeProgram(opcode.EQUAL) vm := load(prog) vm.estack.PushVal(5) vm.estack.PushVal(5) @@ -762,7 +763,7 @@ func TestEQUALGoodInteger(t *testing.T) { } func TestEQUALArrayTrue(t *testing.T) { - prog := makeProgram(DUP, EQUAL) + prog := makeProgram(opcode.DUP, opcode.EQUAL) vm := load(prog) vm.estack.PushVal([]StackItem{}) runVM(t, vm) @@ -771,7 +772,7 @@ func TestEQUALArrayTrue(t *testing.T) { } func TestEQUALArrayFalse(t *testing.T) { - prog := makeProgram(EQUAL) + prog := makeProgram(opcode.EQUAL) vm := load(prog) vm.estack.PushVal([]StackItem{}) vm.estack.PushVal([]StackItem{}) @@ -781,7 +782,7 @@ func TestEQUALArrayFalse(t *testing.T) { } func TestEQUALMapTrue(t *testing.T) { - prog := makeProgram(DUP, EQUAL) + prog := makeProgram(opcode.DUP, opcode.EQUAL) vm := load(prog) vm.estack.Push(&Element{value: NewMapItem()}) runVM(t, vm) @@ -790,7 +791,7 @@ func TestEQUALMapTrue(t *testing.T) { } func TestEQUALMapFalse(t *testing.T) { - prog := makeProgram(EQUAL) + prog := makeProgram(opcode.EQUAL) vm := load(prog) vm.estack.Push(&Element{value: NewMapItem()}) vm.estack.Push(&Element{value: NewMapItem()}) @@ -800,7 +801,7 @@ func TestEQUALMapFalse(t *testing.T) { } func TestNumEqual(t *testing.T) { - prog := makeProgram(NUMEQUAL) + prog := makeProgram(opcode.NUMEQUAL) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -809,7 +810,7 @@ func TestNumEqual(t *testing.T) { } func TestNumNotEqual(t *testing.T) { - prog := makeProgram(NUMNOTEQUAL) + prog := makeProgram(opcode.NUMNOTEQUAL) vm := load(prog) vm.estack.PushVal(2) vm.estack.PushVal(2) @@ -818,7 +819,7 @@ func TestNumNotEqual(t *testing.T) { } func TestINC(t *testing.T) { - prog := makeProgram(INC) + prog := makeProgram(opcode.INC) vm := load(prog) vm.estack.PushVal(1) runVM(t, vm) @@ -826,7 +827,7 @@ func TestINC(t *testing.T) { } func TestINCBigResult(t *testing.T) { - prog := makeProgram(INC, INC) + prog := makeProgram(opcode.INC, opcode.INC) vm := load(prog) x := getBigInt(MaxBigIntegerSizeBits, -2) vm.estack.PushVal(x) @@ -840,7 +841,7 @@ func TestINCBigResult(t *testing.T) { } func TestDECBigResult(t *testing.T) { - prog := makeProgram(DEC, DEC) + prog := makeProgram(opcode.DEC, opcode.DEC) vm := load(prog) x := getBigInt(MaxBigIntegerSizeBits, -2) x.Neg(x) @@ -855,7 +856,7 @@ func TestDECBigResult(t *testing.T) { } func TestNEWARRAYInteger(t *testing.T) { - prog := makeProgram(NEWARRAY) + prog := makeProgram(opcode.NEWARRAY) vm := load(prog) vm.estack.PushVal(1) runVM(t, vm) @@ -864,7 +865,7 @@ func TestNEWARRAYInteger(t *testing.T) { } func TestNEWARRAYStruct(t *testing.T) { - prog := makeProgram(NEWARRAY) + prog := makeProgram(opcode.NEWARRAY) vm := load(prog) arr := []StackItem{makeStackItem(42)} vm.estack.Push(&Element{value: &StructItem{arr}}) @@ -873,13 +874,13 @@ func TestNEWARRAYStruct(t *testing.T) { assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value) } -func testNEWARRAYIssue437(t *testing.T, i1, i2 Instruction, appended bool) { +func testNEWARRAYIssue437(t *testing.T, i1, i2 opcode.Opcode, appended bool) { prog := makeProgram( - PUSH2, i1, - DUP, PUSH3, APPEND, - TOALTSTACK, DUPFROMALTSTACK, i2, - DUP, PUSH4, APPEND, - FROMALTSTACK, PUSH5, APPEND) + opcode.PUSH2, i1, + opcode.DUP, opcode.PUSH3, opcode.APPEND, + opcode.TOALTSTACK, opcode.DUPFROMALTSTACK, i2, + opcode.DUP, opcode.PUSH4, opcode.APPEND, + opcode.FROMALTSTACK, opcode.PUSH5, opcode.APPEND) vm := load(prog) vm.Run() @@ -892,7 +893,7 @@ func testNEWARRAYIssue437(t *testing.T, i1, i2 Instruction, appended bool) { assert.Equal(t, false, vm.HasFailed()) assert.Equal(t, 1, vm.estack.Len()) - if i2 == NEWARRAY { + if i2 == opcode.NEWARRAY { assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value) } else { assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value) @@ -900,14 +901,14 @@ func testNEWARRAYIssue437(t *testing.T, i1, i2 Instruction, appended bool) { } func TestNEWARRAYIssue437(t *testing.T) { - t.Run("Array+Array", func(t *testing.T) { testNEWARRAYIssue437(t, NEWARRAY, NEWARRAY, true) }) - t.Run("Struct+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, NEWSTRUCT, NEWSTRUCT, true) }) - t.Run("Array+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, NEWARRAY, NEWSTRUCT, false) }) - t.Run("Struct+Array", func(t *testing.T) { testNEWARRAYIssue437(t, NEWSTRUCT, NEWARRAY, false) }) + t.Run("Array+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, opcode.NEWARRAY, true) }) + t.Run("Struct+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, opcode.NEWSTRUCT, true) }) + t.Run("Array+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, opcode.NEWSTRUCT, false) }) + t.Run("Struct+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, opcode.NEWARRAY, false) }) } func TestNEWARRAYArray(t *testing.T) { - prog := makeProgram(NEWARRAY) + prog := makeProgram(opcode.NEWARRAY) vm := load(prog) arr := []StackItem{makeStackItem(42)} vm.estack.Push(&Element{value: &ArrayItem{arr}}) @@ -917,7 +918,7 @@ func TestNEWARRAYArray(t *testing.T) { } func TestNEWARRAYByteArray(t *testing.T) { - prog := makeProgram(NEWARRAY) + prog := makeProgram(opcode.NEWARRAY) vm := load(prog) vm.estack.PushVal([]byte{}) runVM(t, vm) @@ -926,14 +927,14 @@ func TestNEWARRAYByteArray(t *testing.T) { } func TestNEWARRAYBadSize(t *testing.T) { - prog := makeProgram(NEWARRAY) + prog := makeProgram(opcode.NEWARRAY) vm := load(prog) vm.estack.PushVal(MaxArraySize + 1) checkVMFailed(t, vm) } func TestNEWSTRUCTInteger(t *testing.T) { - prog := makeProgram(NEWSTRUCT) + prog := makeProgram(opcode.NEWSTRUCT) vm := load(prog) vm.estack.PushVal(1) runVM(t, vm) @@ -942,7 +943,7 @@ func TestNEWSTRUCTInteger(t *testing.T) { } func TestNEWSTRUCTArray(t *testing.T) { - prog := makeProgram(NEWSTRUCT) + prog := makeProgram(opcode.NEWSTRUCT) vm := load(prog) arr := []StackItem{makeStackItem(42)} vm.estack.Push(&Element{value: &ArrayItem{arr}}) @@ -952,7 +953,7 @@ func TestNEWSTRUCTArray(t *testing.T) { } func TestNEWSTRUCTStruct(t *testing.T) { - prog := makeProgram(NEWSTRUCT) + prog := makeProgram(opcode.NEWSTRUCT) vm := load(prog) arr := []StackItem{makeStackItem(42)} vm.estack.Push(&Element{value: &StructItem{arr}}) @@ -962,7 +963,7 @@ func TestNEWSTRUCTStruct(t *testing.T) { } func TestNEWSTRUCTByteArray(t *testing.T) { - prog := makeProgram(NEWSTRUCT) + prog := makeProgram(opcode.NEWSTRUCT) vm := load(prog) vm.estack.PushVal([]byte{}) runVM(t, vm) @@ -971,14 +972,14 @@ func TestNEWSTRUCTByteArray(t *testing.T) { } func TestNEWSTRUCTBadSize(t *testing.T) { - prog := makeProgram(NEWSTRUCT) + prog := makeProgram(opcode.NEWSTRUCT) vm := load(prog) vm.estack.PushVal(MaxArraySize + 1) checkVMFailed(t, vm) } func TestAPPENDArray(t *testing.T) { - prog := makeProgram(DUP, PUSH5, APPEND) + prog := makeProgram(opcode.DUP, opcode.PUSH5, opcode.APPEND) vm := load(prog) vm.estack.Push(&Element{value: &ArrayItem{}}) runVM(t, vm) @@ -987,7 +988,7 @@ func TestAPPENDArray(t *testing.T) { } func TestAPPENDStruct(t *testing.T) { - prog := makeProgram(DUP, PUSH5, APPEND) + prog := makeProgram(opcode.DUP, opcode.PUSH5, opcode.APPEND) vm := load(prog) vm.estack.Push(&Element{value: &StructItem{}}) runVM(t, vm) @@ -996,7 +997,8 @@ func TestAPPENDStruct(t *testing.T) { } func TestAPPENDCloneStruct(t *testing.T) { - prog := makeProgram(DUP, PUSH0, NEWSTRUCT, TOALTSTACK, DUPFROMALTSTACK, APPEND, FROMALTSTACK, PUSH1, APPEND) + prog := makeProgram(opcode.DUP, opcode.PUSH0, opcode.NEWSTRUCT, opcode.TOALTSTACK, + opcode.DUPFROMALTSTACK, opcode.APPEND, opcode.FROMALTSTACK, opcode.PUSH1, opcode.APPEND) vm := load(prog) vm.estack.Push(&Element{value: &ArrayItem{}}) runVM(t, vm) @@ -1007,20 +1009,20 @@ func TestAPPENDCloneStruct(t *testing.T) { } func TestAPPENDBadNoArguments(t *testing.T) { - prog := makeProgram(APPEND) + prog := makeProgram(opcode.APPEND) vm := load(prog) checkVMFailed(t, vm) } func TestAPPENDBad1Argument(t *testing.T) { - prog := makeProgram(APPEND) + prog := makeProgram(opcode.APPEND) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestAPPENDWrongType(t *testing.T) { - prog := makeProgram(APPEND) + prog := makeProgram(opcode.APPEND) vm := load(prog) vm.estack.PushVal([]byte{}) vm.estack.PushVal(1) @@ -1028,7 +1030,7 @@ func TestAPPENDWrongType(t *testing.T) { } func TestAPPENDGoodSizeLimit(t *testing.T) { - prog := makeProgram(NEWARRAY, DUP, PUSH0, APPEND) + prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND) vm := load(prog) vm.estack.PushVal(MaxArraySize - 1) runVM(t, vm) @@ -1037,14 +1039,14 @@ func TestAPPENDGoodSizeLimit(t *testing.T) { } func TestAPPENDBadSizeLimit(t *testing.T) { - prog := makeProgram(NEWARRAY, DUP, PUSH0, APPEND) + prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND) vm := load(prog) vm.estack.PushVal(MaxArraySize) checkVMFailed(t, vm) } func TestPICKITEMBadIndex(t *testing.T) { - prog := makeProgram(PICKITEM) + prog := makeProgram(opcode.PICKITEM) vm := load(prog) vm.estack.PushVal([]StackItem{}) vm.estack.PushVal(0) @@ -1052,7 +1054,7 @@ func TestPICKITEMBadIndex(t *testing.T) { } func TestPICKITEMArray(t *testing.T) { - prog := makeProgram(PICKITEM) + prog := makeProgram(opcode.PICKITEM) vm := load(prog) vm.estack.PushVal([]StackItem{makeStackItem(1), makeStackItem(2)}) vm.estack.PushVal(1) @@ -1062,7 +1064,7 @@ func TestPICKITEMArray(t *testing.T) { } func TestPICKITEMByteArray(t *testing.T) { - prog := makeProgram(PICKITEM) + prog := makeProgram(opcode.PICKITEM) vm := load(prog) vm.estack.PushVal([]byte{1, 2}) vm.estack.PushVal(1) @@ -1072,7 +1074,7 @@ func TestPICKITEMByteArray(t *testing.T) { } func TestPICKITEMMap(t *testing.T) { - prog := makeProgram(PICKITEM) + prog := makeProgram(opcode.PICKITEM) vm := load(prog) m := NewMapItem() @@ -1086,7 +1088,7 @@ func TestPICKITEMMap(t *testing.T) { } func TestSETITEMMap(t *testing.T) { - prog := makeProgram(SETITEM, PICKITEM) + prog := makeProgram(opcode.SETITEM, opcode.PICKITEM) vm := load(prog) m := NewMapItem() @@ -1103,7 +1105,7 @@ func TestSETITEMMap(t *testing.T) { } func TestSETITEMBigMapBad(t *testing.T) { - prog := makeProgram(SETITEM) + prog := makeProgram(opcode.SETITEM) vm := load(prog) m := NewMapItem() @@ -1118,7 +1120,7 @@ func TestSETITEMBigMapBad(t *testing.T) { } func TestSETITEMBigMapGood(t *testing.T) { - prog := makeProgram(SETITEM) + prog := makeProgram(opcode.SETITEM) vm := load(prog) m := NewMapItem() @@ -1133,13 +1135,13 @@ func TestSETITEMBigMapGood(t *testing.T) { } func TestSIZENoArgument(t *testing.T) { - prog := makeProgram(SIZE) + prog := makeProgram(opcode.SIZE) vm := load(prog) checkVMFailed(t, vm) } func TestSIZEByteArray(t *testing.T) { - prog := makeProgram(SIZE) + prog := makeProgram(opcode.SIZE) vm := load(prog) vm.estack.PushVal([]byte{0, 1}) runVM(t, vm) @@ -1148,7 +1150,7 @@ func TestSIZEByteArray(t *testing.T) { } func TestSIZEBool(t *testing.T) { - prog := makeProgram(SIZE) + prog := makeProgram(opcode.SIZE) vm := load(prog) vm.estack.PushVal(false) runVM(t, vm) @@ -1159,7 +1161,7 @@ func TestSIZEBool(t *testing.T) { } func TestARRAYSIZEArray(t *testing.T) { - prog := makeProgram(ARRAYSIZE) + prog := makeProgram(opcode.ARRAYSIZE) vm := load(prog) vm.estack.PushVal([]StackItem{ makeStackItem(1), @@ -1171,7 +1173,7 @@ func TestARRAYSIZEArray(t *testing.T) { } func TestARRAYSIZEMap(t *testing.T) { - prog := makeProgram(ARRAYSIZE) + prog := makeProgram(opcode.ARRAYSIZE) vm := load(prog) m := NewMapItem() @@ -1185,7 +1187,7 @@ func TestARRAYSIZEMap(t *testing.T) { } func TestKEYSMap(t *testing.T) { - prog := makeProgram(KEYS) + prog := makeProgram(opcode.KEYS) vm := load(prog) m := NewMapItem() @@ -1203,20 +1205,20 @@ func TestKEYSMap(t *testing.T) { } func TestKEYSNoArgument(t *testing.T) { - prog := makeProgram(KEYS) + prog := makeProgram(opcode.KEYS) vm := load(prog) checkVMFailed(t, vm) } func TestKEYSWrongType(t *testing.T) { - prog := makeProgram(KEYS) + prog := makeProgram(opcode.KEYS) vm := load(prog) vm.estack.PushVal([]StackItem{}) checkVMFailed(t, vm) } func TestVALUESMap(t *testing.T) { - prog := makeProgram(VALUES) + prog := makeProgram(opcode.VALUES) vm := load(prog) m := NewMapItem() @@ -1234,7 +1236,7 @@ func TestVALUESMap(t *testing.T) { } func TestVALUESArray(t *testing.T) { - prog := makeProgram(VALUES) + prog := makeProgram(opcode.VALUES) vm := load(prog) vm.estack.PushVal([]StackItem{makeStackItem(4)}) runVM(t, vm) @@ -1243,20 +1245,20 @@ func TestVALUESArray(t *testing.T) { } func TestVALUESNoArgument(t *testing.T) { - prog := makeProgram(VALUES) + prog := makeProgram(opcode.VALUES) vm := load(prog) checkVMFailed(t, vm) } func TestVALUESWrongType(t *testing.T) { - prog := makeProgram(VALUES) + prog := makeProgram(opcode.VALUES) vm := load(prog) vm.estack.PushVal(5) checkVMFailed(t, vm) } func TestHASKEYArrayTrue(t *testing.T) { - prog := makeProgram(PUSH5, NEWARRAY, PUSH4, HASKEY) + prog := makeProgram(opcode.PUSH5, opcode.NEWARRAY, opcode.PUSH4, opcode.HASKEY) vm := load(prog) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) @@ -1264,7 +1266,7 @@ func TestHASKEYArrayTrue(t *testing.T) { } func TestHASKEYArrayFalse(t *testing.T) { - prog := makeProgram(PUSH5, NEWARRAY, PUSH5, HASKEY) + prog := makeProgram(opcode.PUSH5, opcode.NEWARRAY, opcode.PUSH5, opcode.HASKEY) vm := load(prog) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) @@ -1272,7 +1274,7 @@ func TestHASKEYArrayFalse(t *testing.T) { } func TestHASKEYStructTrue(t *testing.T) { - prog := makeProgram(PUSH5, NEWSTRUCT, PUSH4, HASKEY) + prog := makeProgram(opcode.PUSH5, opcode.NEWSTRUCT, opcode.PUSH4, opcode.HASKEY) vm := load(prog) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) @@ -1280,7 +1282,7 @@ func TestHASKEYStructTrue(t *testing.T) { } func TestHASKEYStructFalse(t *testing.T) { - prog := makeProgram(PUSH5, NEWSTRUCT, PUSH5, HASKEY) + prog := makeProgram(opcode.PUSH5, opcode.NEWSTRUCT, opcode.PUSH5, opcode.HASKEY) vm := load(prog) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) @@ -1288,7 +1290,7 @@ func TestHASKEYStructFalse(t *testing.T) { } func TestHASKEYMapTrue(t *testing.T) { - prog := makeProgram(HASKEY) + prog := makeProgram(opcode.HASKEY) vm := load(prog) m := NewMapItem() m.Add(makeStackItem(5), makeStackItem(6)) @@ -1300,7 +1302,7 @@ func TestHASKEYMapTrue(t *testing.T) { } func TestHASKEYMapFalse(t *testing.T) { - prog := makeProgram(HASKEY) + prog := makeProgram(opcode.HASKEY) vm := load(prog) m := NewMapItem() m.Add(makeStackItem(5), makeStackItem(6)) @@ -1312,20 +1314,20 @@ func TestHASKEYMapFalse(t *testing.T) { } func TestHASKEYNoArguments(t *testing.T) { - prog := makeProgram(HASKEY) + prog := makeProgram(opcode.HASKEY) vm := load(prog) checkVMFailed(t, vm) } func TestHASKEY1Argument(t *testing.T) { - prog := makeProgram(HASKEY) + prog := makeProgram(opcode.HASKEY) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestHASKEYWrongKeyType(t *testing.T) { - prog := makeProgram(HASKEY) + prog := makeProgram(opcode.HASKEY) vm := load(prog) vm.estack.PushVal([]StackItem{}) vm.estack.PushVal([]StackItem{}) @@ -1333,7 +1335,7 @@ func TestHASKEYWrongKeyType(t *testing.T) { } func TestHASKEYWrongCollectionType(t *testing.T) { - prog := makeProgram(HASKEY) + prog := makeProgram(opcode.HASKEY) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -1341,20 +1343,20 @@ func TestHASKEYWrongCollectionType(t *testing.T) { } func TestSIGNNoArgument(t *testing.T) { - prog := makeProgram(SIGN) + prog := makeProgram(opcode.SIGN) vm := load(prog) checkVMFailed(t, vm) } func TestSIGNWrongType(t *testing.T) { - prog := makeProgram(SIGN) + prog := makeProgram(opcode.SIGN) vm := load(prog) vm.estack.PushVal([]StackItem{}) checkVMFailed(t, vm) } func TestSIGNBool(t *testing.T) { - prog := makeProgram(SIGN) + prog := makeProgram(opcode.SIGN) vm := load(prog) vm.estack.PushVal(false) runVM(t, vm) @@ -1363,7 +1365,7 @@ func TestSIGNBool(t *testing.T) { } func TestSIGNPositiveInt(t *testing.T) { - prog := makeProgram(SIGN) + prog := makeProgram(opcode.SIGN) vm := load(prog) vm.estack.PushVal(1) runVM(t, vm) @@ -1372,7 +1374,7 @@ func TestSIGNPositiveInt(t *testing.T) { } func TestSIGNNegativeInt(t *testing.T) { - prog := makeProgram(SIGN) + prog := makeProgram(opcode.SIGN) vm := load(prog) vm.estack.PushVal(-1) runVM(t, vm) @@ -1381,7 +1383,7 @@ func TestSIGNNegativeInt(t *testing.T) { } func TestSIGNZero(t *testing.T) { - prog := makeProgram(SIGN) + prog := makeProgram(opcode.SIGN) vm := load(prog) vm.estack.PushVal(0) runVM(t, vm) @@ -1390,7 +1392,7 @@ func TestSIGNZero(t *testing.T) { } func TestSIGNByteArray(t *testing.T) { - prog := makeProgram(SIGN) + prog := makeProgram(opcode.SIGN) vm := load(prog) vm.estack.PushVal([]byte{0, 1}) runVM(t, vm) @@ -1399,15 +1401,15 @@ func TestSIGNByteArray(t *testing.T) { } func TestAppCall(t *testing.T) { - prog := []byte{byte(APPCALL)} + prog := []byte{byte(opcode.APPCALL)} hash := util.Uint160{} prog = append(prog, hash.Bytes()...) - prog = append(prog, byte(RET)) + prog = append(prog, byte(opcode.RET)) vm := load(prog) vm.SetScriptGetter(func(in util.Uint160) []byte { if in.Equals(hash) { - return makeProgram(DEPTH) + return makeProgram(opcode.DEPTH) } return nil }) @@ -1432,7 +1434,7 @@ func TestSimpleCall(t *testing.T) { } func TestNZtrue(t *testing.T) { - prog := makeProgram(NZ) + prog := makeProgram(opcode.NZ) vm := load(prog) vm.estack.PushVal(1) runVM(t, vm) @@ -1440,7 +1442,7 @@ func TestNZtrue(t *testing.T) { } func TestNZfalse(t *testing.T) { - prog := makeProgram(NZ) + prog := makeProgram(opcode.NZ) vm := load(prog) vm.estack.PushVal(0) runVM(t, vm) @@ -1448,21 +1450,21 @@ func TestNZfalse(t *testing.T) { } func TestPICKbadNoitem(t *testing.T) { - prog := makeProgram(PICK) + prog := makeProgram(opcode.PICK) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestPICKbadNegative(t *testing.T) { - prog := makeProgram(PICK) + prog := makeProgram(opcode.PICK) vm := load(prog) vm.estack.PushVal(-1) checkVMFailed(t, vm) } func TestPICKgood(t *testing.T) { - prog := makeProgram(PICK) + prog := makeProgram(opcode.PICK) result := 2 vm := load(prog) vm.estack.PushVal(0) @@ -1477,7 +1479,7 @@ func TestPICKgood(t *testing.T) { } func TestROTBad(t *testing.T) { - prog := makeProgram(ROT) + prog := makeProgram(opcode.ROT) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -1485,7 +1487,7 @@ func TestROTBad(t *testing.T) { } func TestROTGood(t *testing.T) { - prog := makeProgram(ROT) + prog := makeProgram(opcode.ROT) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -1498,14 +1500,14 @@ func TestROTGood(t *testing.T) { } func TestXTUCKbadNoitem(t *testing.T) { - prog := makeProgram(XTUCK) + prog := makeProgram(opcode.XTUCK) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestXTUCKbadNoN(t *testing.T) { - prog := makeProgram(XTUCK) + prog := makeProgram(opcode.XTUCK) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -1513,14 +1515,14 @@ func TestXTUCKbadNoN(t *testing.T) { } func TestXTUCKbadNegative(t *testing.T) { - prog := makeProgram(XTUCK) + prog := makeProgram(opcode.XTUCK) vm := load(prog) vm.estack.PushVal(-1) checkVMFailed(t, vm) } func TestXTUCKbadZero(t *testing.T) { - prog := makeProgram(XTUCK) + prog := makeProgram(opcode.XTUCK) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(0) @@ -1528,7 +1530,7 @@ func TestXTUCKbadZero(t *testing.T) { } func TestXTUCKgood(t *testing.T) { - prog := makeProgram(XTUCK) + prog := makeProgram(opcode.XTUCK) topelement := 5 xtuckdepth := 3 vm := load(prog) @@ -1545,20 +1547,20 @@ func TestXTUCKgood(t *testing.T) { } func TestTUCKbadNoitems(t *testing.T) { - prog := makeProgram(TUCK) + prog := makeProgram(opcode.TUCK) vm := load(prog) checkVMFailed(t, vm) } func TestTUCKbadNoitem(t *testing.T) { - prog := makeProgram(TUCK) + prog := makeProgram(opcode.TUCK) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestTUCKgood(t *testing.T) { - prog := makeProgram(TUCK) + prog := makeProgram(opcode.TUCK) vm := load(prog) vm.estack.PushVal(42) vm.estack.PushVal(34) @@ -1569,7 +1571,7 @@ func TestTUCKgood(t *testing.T) { } func TestTUCKgood2(t *testing.T) { - prog := makeProgram(TUCK) + prog := makeProgram(opcode.TUCK) vm := load(prog) vm.estack.PushVal(11) vm.estack.PushVal(42) @@ -1582,7 +1584,7 @@ func TestTUCKgood2(t *testing.T) { } func TestOVERbadNoitem(t *testing.T) { - prog := makeProgram(OVER) + prog := makeProgram(opcode.OVER) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) @@ -1591,13 +1593,13 @@ func TestOVERbadNoitem(t *testing.T) { } func TestOVERbadNoitems(t *testing.T) { - prog := makeProgram(OVER) + prog := makeProgram(opcode.OVER) vm := load(prog) checkVMFailed(t, vm) } func TestOVERgood(t *testing.T) { - prog := makeProgram(OVER) + prog := makeProgram(opcode.OVER) vm := load(prog) vm.estack.PushVal(42) vm.estack.PushVal(34) @@ -1609,14 +1611,14 @@ func TestOVERgood(t *testing.T) { } func TestNIPBadNoItem(t *testing.T) { - prog := makeProgram(NIP) + prog := makeProgram(opcode.NIP) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestNIPGood(t *testing.T) { - prog := makeProgram(NIP) + prog := makeProgram(opcode.NIP) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -1626,13 +1628,13 @@ func TestNIPGood(t *testing.T) { } func TestDROPBadNoItem(t *testing.T) { - prog := makeProgram(DROP) + prog := makeProgram(opcode.DROP) vm := load(prog) checkVMFailed(t, vm) } func TestDROPGood(t *testing.T) { - prog := makeProgram(DROP) + prog := makeProgram(opcode.DROP) vm := load(prog) vm.estack.PushVal(1) runVM(t, vm) @@ -1640,13 +1642,13 @@ func TestDROPGood(t *testing.T) { } func TestXDROPbadNoitem(t *testing.T) { - prog := makeProgram(XDROP) + prog := makeProgram(opcode.XDROP) vm := load(prog) checkVMFailed(t, vm) } func TestXDROPbadNoN(t *testing.T) { - prog := makeProgram(XDROP) + prog := makeProgram(opcode.XDROP) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(2) @@ -1654,7 +1656,7 @@ func TestXDROPbadNoN(t *testing.T) { } func TestXDROPbadNegative(t *testing.T) { - prog := makeProgram(XDROP) + prog := makeProgram(opcode.XDROP) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(-1) @@ -1662,7 +1664,7 @@ func TestXDROPbadNegative(t *testing.T) { } func TestXDROPgood(t *testing.T) { - prog := makeProgram(XDROP) + prog := makeProgram(opcode.XDROP) vm := load(prog) vm.estack.PushVal(0) vm.estack.PushVal(1) @@ -1675,13 +1677,13 @@ func TestXDROPgood(t *testing.T) { } func TestINVERTbadNoitem(t *testing.T) { - prog := makeProgram(INVERT) + prog := makeProgram(opcode.INVERT) vm := load(prog) checkVMFailed(t, vm) } func TestINVERTgood1(t *testing.T) { - prog := makeProgram(INVERT) + prog := makeProgram(opcode.INVERT) vm := load(prog) vm.estack.PushVal(0) runVM(t, vm) @@ -1689,7 +1691,7 @@ func TestINVERTgood1(t *testing.T) { } func TestINVERTgood2(t *testing.T) { - prog := makeProgram(INVERT) + prog := makeProgram(opcode.INVERT) vm := load(prog) vm.estack.PushVal(-1) runVM(t, vm) @@ -1697,7 +1699,7 @@ func TestINVERTgood2(t *testing.T) { } func TestINVERTgood3(t *testing.T) { - prog := makeProgram(INVERT) + prog := makeProgram(opcode.INVERT) vm := load(prog) vm.estack.PushVal(0x69) runVM(t, vm) @@ -1705,20 +1707,20 @@ func TestINVERTgood3(t *testing.T) { } func TestCATBadNoArgs(t *testing.T) { - prog := makeProgram(CAT) + prog := makeProgram(opcode.CAT) vm := load(prog) checkVMFailed(t, vm) } func TestCATBadOneArg(t *testing.T) { - prog := makeProgram(CAT) + prog := makeProgram(opcode.CAT) vm := load(prog) vm.estack.PushVal([]byte("abc")) checkVMFailed(t, vm) } func TestCATBadBigItem(t *testing.T) { - prog := makeProgram(CAT) + prog := makeProgram(opcode.CAT) vm := load(prog) vm.estack.PushVal(make([]byte, MaxItemSize/2+1)) vm.estack.PushVal(make([]byte, MaxItemSize/2+1)) @@ -1727,7 +1729,7 @@ func TestCATBadBigItem(t *testing.T) { } func TestCATGood(t *testing.T) { - prog := makeProgram(CAT) + prog := makeProgram(opcode.CAT) vm := load(prog) vm.estack.PushVal([]byte("abc")) vm.estack.PushVal([]byte("def")) @@ -1737,7 +1739,7 @@ func TestCATGood(t *testing.T) { } func TestCATInt0ByteArray(t *testing.T) { - prog := makeProgram(CAT) + prog := makeProgram(opcode.CAT) vm := load(prog) vm.estack.PushVal(0) vm.estack.PushVal([]byte{}) @@ -1747,7 +1749,7 @@ func TestCATInt0ByteArray(t *testing.T) { } func TestCATByteArrayInt1(t *testing.T) { - prog := makeProgram(CAT) + prog := makeProgram(opcode.CAT) vm := load(prog) vm.estack.PushVal([]byte{}) vm.estack.PushVal(1) @@ -1757,20 +1759,20 @@ func TestCATByteArrayInt1(t *testing.T) { } func TestSUBSTRBadNoArgs(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) checkVMFailed(t, vm) } func TestSUBSTRBadOneArg(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestSUBSTRBadTwoArgs(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) vm.estack.PushVal(0) vm.estack.PushVal(2) @@ -1778,7 +1780,7 @@ func TestSUBSTRBadTwoArgs(t *testing.T) { } func TestSUBSTRGood(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(1) @@ -1789,7 +1791,7 @@ func TestSUBSTRGood(t *testing.T) { } func TestSUBSTRBadOffset(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(7) @@ -1803,7 +1805,7 @@ func TestSUBSTRBadOffset(t *testing.T) { } func TestSUBSTRBigLen(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(1) @@ -1814,7 +1816,7 @@ func TestSUBSTRBigLen(t *testing.T) { } func TestSUBSTRBad387(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) b := make([]byte, 6, 20) copy(b, "abcdef") @@ -1827,7 +1829,7 @@ func TestSUBSTRBad387(t *testing.T) { } func TestSUBSTRBadNegativeOffset(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(-1) @@ -1836,7 +1838,7 @@ func TestSUBSTRBadNegativeOffset(t *testing.T) { } func TestSUBSTRBadNegativeLen(t *testing.T) { - prog := makeProgram(SUBSTR) + prog := makeProgram(opcode.SUBSTR) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(3) @@ -1845,20 +1847,20 @@ func TestSUBSTRBadNegativeLen(t *testing.T) { } func TestLEFTBadNoArgs(t *testing.T) { - prog := makeProgram(LEFT) + prog := makeProgram(opcode.LEFT) vm := load(prog) checkVMFailed(t, vm) } func TestLEFTBadNoString(t *testing.T) { - prog := makeProgram(LEFT) + prog := makeProgram(opcode.LEFT) vm := load(prog) vm.estack.PushVal(2) checkVMFailed(t, vm) } func TestLEFTBadNegativeLen(t *testing.T) { - prog := makeProgram(LEFT) + prog := makeProgram(opcode.LEFT) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(-1) @@ -1866,7 +1868,7 @@ func TestLEFTBadNegativeLen(t *testing.T) { } func TestLEFTGood(t *testing.T) { - prog := makeProgram(LEFT) + prog := makeProgram(opcode.LEFT) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(2) @@ -1876,7 +1878,7 @@ func TestLEFTGood(t *testing.T) { } func TestLEFTGoodLen(t *testing.T) { - prog := makeProgram(LEFT) + prog := makeProgram(opcode.LEFT) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(8) @@ -1886,20 +1888,20 @@ func TestLEFTGoodLen(t *testing.T) { } func TestRIGHTBadNoArgs(t *testing.T) { - prog := makeProgram(RIGHT) + prog := makeProgram(opcode.RIGHT) vm := load(prog) checkVMFailed(t, vm) } func TestRIGHTBadNoString(t *testing.T) { - prog := makeProgram(RIGHT) + prog := makeProgram(opcode.RIGHT) vm := load(prog) vm.estack.PushVal(2) checkVMFailed(t, vm) } func TestRIGHTBadNegativeLen(t *testing.T) { - prog := makeProgram(RIGHT) + prog := makeProgram(opcode.RIGHT) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(-1) @@ -1907,7 +1909,7 @@ func TestRIGHTBadNegativeLen(t *testing.T) { } func TestRIGHTGood(t *testing.T) { - prog := makeProgram(RIGHT) + prog := makeProgram(opcode.RIGHT) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(2) @@ -1917,7 +1919,7 @@ func TestRIGHTGood(t *testing.T) { } func TestRIGHTBadLen(t *testing.T) { - prog := makeProgram(RIGHT) + prog := makeProgram(opcode.RIGHT) vm := load(prog) vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(8) @@ -1925,14 +1927,14 @@ func TestRIGHTBadLen(t *testing.T) { } func TestPACKBadLen(t *testing.T) { - prog := makeProgram(PACK) + prog := makeProgram(opcode.PACK) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestPACKBigLen(t *testing.T) { - prog := makeProgram(PACK) + prog := makeProgram(opcode.PACK) vm := load(prog) for i := 0; i <= MaxArraySize; i++ { vm.estack.PushVal(0) @@ -1942,7 +1944,7 @@ func TestPACKBigLen(t *testing.T) { } func TestPACKGoodZeroLen(t *testing.T) { - prog := makeProgram(PACK) + prog := makeProgram(opcode.PACK) vm := load(prog) vm.estack.PushVal(0) runVM(t, vm) @@ -1951,7 +1953,7 @@ func TestPACKGoodZeroLen(t *testing.T) { } func TestPACKGood(t *testing.T) { - prog := makeProgram(PACK) + prog := makeProgram(opcode.PACK) elements := []int{55, 34, 42} vm := load(prog) // canary @@ -1972,14 +1974,14 @@ func TestPACKGood(t *testing.T) { } func TestUNPACKBadNotArray(t *testing.T) { - prog := makeProgram(UNPACK) + prog := makeProgram(opcode.UNPACK) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestUNPACKGood(t *testing.T) { - prog := makeProgram(UNPACK) + prog := makeProgram(opcode.UNPACK) elements := []int{55, 34, 42} vm := load(prog) // canary @@ -1995,18 +1997,18 @@ func TestUNPACKGood(t *testing.T) { } func TestREVERSEBadNotArray(t *testing.T) { - prog := makeProgram(REVERSE) + prog := makeProgram(opcode.REVERSE) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } -func testREVERSEIssue437(t *testing.T, i1, i2 Instruction, reversed bool) { +func testREVERSEIssue437(t *testing.T, i1, i2 opcode.Opcode, reversed bool) { prog := makeProgram( - PUSH0, i1, - DUP, PUSH1, APPEND, - DUP, PUSH2, APPEND, - DUP, i2, REVERSE) + opcode.PUSH0, i1, + opcode.DUP, opcode.PUSH1, opcode.APPEND, + opcode.DUP, opcode.PUSH2, opcode.APPEND, + opcode.DUP, i2, opcode.REVERSE) vm := load(prog) vm.Run() @@ -2020,7 +2022,7 @@ func testREVERSEIssue437(t *testing.T, i1, i2 Instruction, reversed bool) { } assert.Equal(t, false, vm.HasFailed()) assert.Equal(t, 1, vm.estack.Len()) - if i1 == NEWARRAY { + if i1 == opcode.NEWARRAY { assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value) } else { assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value) @@ -2028,14 +2030,14 @@ func testREVERSEIssue437(t *testing.T, i1, i2 Instruction, reversed bool) { } func TestREVERSEIssue437(t *testing.T) { - t.Run("Array+Array", func(t *testing.T) { testREVERSEIssue437(t, NEWARRAY, NEWARRAY, true) }) - t.Run("Struct+Struct", func(t *testing.T) { testREVERSEIssue437(t, NEWSTRUCT, NEWSTRUCT, true) }) - t.Run("Array+Struct", func(t *testing.T) { testREVERSEIssue437(t, NEWARRAY, NEWSTRUCT, false) }) - t.Run("Struct+Array", func(t *testing.T) { testREVERSEIssue437(t, NEWSTRUCT, NEWARRAY, false) }) + t.Run("Array+Array", func(t *testing.T) { testREVERSEIssue437(t, opcode.NEWARRAY, opcode.NEWARRAY, true) }) + t.Run("Struct+Struct", func(t *testing.T) { testREVERSEIssue437(t, opcode.NEWSTRUCT, opcode.NEWSTRUCT, true) }) + t.Run("Array+Struct", func(t *testing.T) { testREVERSEIssue437(t, opcode.NEWARRAY, opcode.NEWSTRUCT, false) }) + t.Run("Struct+Array", func(t *testing.T) { testREVERSEIssue437(t, opcode.NEWSTRUCT, opcode.NEWARRAY, false) }) } func TestREVERSEGoodOneElem(t *testing.T) { - prog := makeProgram(DUP, REVERSE) + prog := makeProgram(opcode.DUP, opcode.REVERSE) elements := []int{22} vm := load(prog) vm.estack.PushVal(1) @@ -2054,7 +2056,7 @@ func TestREVERSEGoodStruct(t *testing.T) { eall := [][]int{eodd, even} for _, elements := range eall { - prog := makeProgram(DUP, REVERSE) + prog := makeProgram(opcode.DUP, opcode.REVERSE) vm := load(prog) vm.estack.PushVal(1) @@ -2082,7 +2084,7 @@ func TestREVERSEGood(t *testing.T) { eall := [][]int{eodd, even} for _, elements := range eall { - prog := makeProgram(DUP, REVERSE) + prog := makeProgram(opcode.DUP, opcode.REVERSE) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(elements) @@ -2099,20 +2101,20 @@ func TestREVERSEGood(t *testing.T) { } func TestREMOVEBadNoArgs(t *testing.T) { - prog := makeProgram(REMOVE) + prog := makeProgram(opcode.REMOVE) vm := load(prog) checkVMFailed(t, vm) } func TestREMOVEBadOneArg(t *testing.T) { - prog := makeProgram(REMOVE) + prog := makeProgram(opcode.REMOVE) vm := load(prog) vm.estack.PushVal(1) checkVMFailed(t, vm) } func TestREMOVEBadNotArray(t *testing.T) { - prog := makeProgram(REMOVE) + prog := makeProgram(opcode.REMOVE) vm := load(prog) vm.estack.PushVal(1) vm.estack.PushVal(1) @@ -2120,7 +2122,7 @@ func TestREMOVEBadNotArray(t *testing.T) { } func TestREMOVEBadIndex(t *testing.T) { - prog := makeProgram(REMOVE) + prog := makeProgram(opcode.REMOVE) elements := []int{22, 34, 42, 55, 81} vm := load(prog) vm.estack.PushVal(elements) @@ -2129,7 +2131,7 @@ func TestREMOVEBadIndex(t *testing.T) { } func TestREMOVEGood(t *testing.T) { - prog := makeProgram(DUP, PUSH2, REMOVE) + prog := makeProgram(opcode.DUP, opcode.PUSH2, opcode.REMOVE) elements := []int{22, 34, 42, 55, 81} reselements := []int{22, 34, 55, 81} vm := load(prog) @@ -2142,7 +2144,7 @@ func TestREMOVEGood(t *testing.T) { } func TestREMOVEMap(t *testing.T) { - prog := makeProgram(REMOVE, PUSH5, HASKEY) + prog := makeProgram(opcode.REMOVE, opcode.PUSH5, opcode.HASKEY) vm := load(prog) m := NewMapItem() @@ -2158,13 +2160,13 @@ func TestREMOVEMap(t *testing.T) { } func TestCHECKSIGNoArgs(t *testing.T) { - prog := makeProgram(CHECKSIG) + prog := makeProgram(opcode.CHECKSIG) vm := load(prog) checkVMFailed(t, vm) } func TestCHECKSIGOneArg(t *testing.T) { - prog := makeProgram(CHECKSIG) + prog := makeProgram(opcode.CHECKSIG) pk, err := keys.NewPrivateKey() assert.Nil(t, err) pbytes := pk.PublicKey().Bytes() @@ -2174,7 +2176,7 @@ func TestCHECKSIGOneArg(t *testing.T) { } func TestCHECKSIGNoSigLoaded(t *testing.T) { - prog := makeProgram(CHECKSIG) + prog := makeProgram(opcode.CHECKSIG) pk, err := keys.NewPrivateKey() assert.Nil(t, err) msg := "NEO - An Open Network For Smart Economy" @@ -2188,7 +2190,7 @@ func TestCHECKSIGNoSigLoaded(t *testing.T) { } func TestCHECKSIGBadKey(t *testing.T) { - prog := makeProgram(CHECKSIG) + prog := makeProgram(opcode.CHECKSIG) pk, err := keys.NewPrivateKey() assert.Nil(t, err) msg := []byte("NEO - An Open Network For Smart Economy") @@ -2203,7 +2205,7 @@ func TestCHECKSIGBadKey(t *testing.T) { } func TestCHECKSIGWrongSig(t *testing.T) { - prog := makeProgram(CHECKSIG) + prog := makeProgram(opcode.CHECKSIG) pk, err := keys.NewPrivateKey() assert.Nil(t, err) msg := []byte("NEO - An Open Network For Smart Economy") @@ -2220,7 +2222,7 @@ func TestCHECKSIGWrongSig(t *testing.T) { } func TestCHECKSIGGood(t *testing.T) { - prog := makeProgram(CHECKSIG) + prog := makeProgram(opcode.CHECKSIG) pk, err := keys.NewPrivateKey() assert.Nil(t, err) msg := []byte("NEO - An Open Network For Smart Economy") @@ -2237,7 +2239,7 @@ func TestCHECKSIGGood(t *testing.T) { } func TestVERIFYGood(t *testing.T) { - prog := makeProgram(VERIFY) + prog := makeProgram(opcode.VERIFY) pk, err := keys.NewPrivateKey() assert.Nil(t, err) msg := []byte("NEO - An Open Network For Smart Economy") @@ -2254,7 +2256,7 @@ func TestVERIFYGood(t *testing.T) { } func TestVERIFYBad(t *testing.T) { - prog := makeProgram(VERIFY) + prog := makeProgram(opcode.VERIFY) pk, err := keys.NewPrivateKey() assert.Nil(t, err) msg := []byte("NEO - An Open Network For Smart Economy") @@ -2271,13 +2273,13 @@ func TestVERIFYBad(t *testing.T) { } func TestCHECKMULTISIGNoArgs(t *testing.T) { - prog := makeProgram(CHECKMULTISIG) + prog := makeProgram(opcode.CHECKMULTISIG) vm := load(prog) checkVMFailed(t, vm) } func TestCHECKMULTISIGOneArg(t *testing.T) { - prog := makeProgram(CHECKMULTISIG) + prog := makeProgram(opcode.CHECKMULTISIG) pk, err := keys.NewPrivateKey() assert.Nil(t, err) vm := load(prog) @@ -2287,7 +2289,7 @@ func TestCHECKMULTISIGOneArg(t *testing.T) { } func TestCHECKMULTISIGNotEnoughKeys(t *testing.T) { - prog := makeProgram(CHECKMULTISIG) + prog := makeProgram(opcode.CHECKMULTISIG) pk1, err := keys.NewPrivateKey() assert.Nil(t, err) pk2, err := keys.NewPrivateKey() @@ -2306,7 +2308,7 @@ func TestCHECKMULTISIGNotEnoughKeys(t *testing.T) { } func TestCHECKMULTISIGNoHash(t *testing.T) { - prog := makeProgram(CHECKMULTISIG) + prog := makeProgram(opcode.CHECKMULTISIG) pk1, err := keys.NewPrivateKey() assert.Nil(t, err) pk2, err := keys.NewPrivateKey() @@ -2325,7 +2327,7 @@ func TestCHECKMULTISIGNoHash(t *testing.T) { } func TestCHECKMULTISIGBadKey(t *testing.T) { - prog := makeProgram(CHECKMULTISIG) + prog := makeProgram(opcode.CHECKMULTISIG) pk1, err := keys.NewPrivateKey() assert.Nil(t, err) pk2, err := keys.NewPrivateKey() @@ -2345,7 +2347,7 @@ func TestCHECKMULTISIGBadKey(t *testing.T) { } func TestCHECKMULTISIGBadSig(t *testing.T) { - prog := makeProgram(CHECKMULTISIG) + prog := makeProgram(opcode.CHECKMULTISIG) pk1, err := keys.NewPrivateKey() assert.Nil(t, err) pk2, err := keys.NewPrivateKey() @@ -2367,7 +2369,7 @@ func TestCHECKMULTISIGBadSig(t *testing.T) { } func TestCHECKMULTISIGGood(t *testing.T) { - prog := makeProgram(CHECKMULTISIG) + prog := makeProgram(opcode.CHECKMULTISIG) pk1, err := keys.NewPrivateKey() assert.Nil(t, err) pk2, err := keys.NewPrivateKey() @@ -2388,12 +2390,12 @@ func TestCHECKMULTISIGGood(t *testing.T) { assert.Equal(t, true, vm.estack.Pop().Bool()) } -func makeProgram(opcodes ...Instruction) []byte { +func makeProgram(opcodes ...opcode.Opcode) []byte { prog := make([]byte, len(opcodes)+1) // RET for i := 0; i < len(opcodes); i++ { prog[i] = byte(opcodes[i]) } - prog[len(prog)-1] = byte(RET) + prog[len(prog)-1] = byte(opcode.RET) return prog } From 138e1256463b1ec1a11bada585391e3466f4a58e Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 3 Dec 2019 17:25:25 +0300 Subject: [PATCH 2/5] *: remove duplicate functions producing verification script Drop wif.GetVerificationScript(), drop smartcontract.CreateSignatureRedeemScript(), add GetVerificationScript() directly to the PublicKey and use it everywhere. --- pkg/consensus/payload.go | 8 +------- pkg/core/interop_system.go | 7 +------ pkg/crypto/keys/publickey.go | 17 ++++++++++++----- pkg/crypto/keys/wif.go | 16 ---------------- pkg/rpc/txBuilder.go | 2 +- pkg/smartcontract/contract.go | 15 --------------- 6 files changed, 15 insertions(+), 50 deletions(-) diff --git a/pkg/consensus/payload.go b/pkg/consensus/payload.go index e80f4bb79..fce529568 100644 --- a/pkg/consensus/payload.go +++ b/pkg/consensus/payload.go @@ -7,7 +7,6 @@ import ( "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/io" - "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" @@ -189,13 +188,8 @@ func (p *Payload) Sign(key *privateKey) error { return err } - verif, err := smartcontract.CreateSignatureRedeemScript(key.PublicKey()) - if err != nil { - return err - } - p.Witness.InvocationScript = append([]byte{byte(opcode.PUSHBYTES64)}, sig...) - p.Witness.VerificationScript = verif + p.Witness.VerificationScript = key.PublicKey().GetVerificationScript() return nil } diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 70bb85bbb..1d8a4a981 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -8,7 +8,6 @@ import ( "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" "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" gherr "github.com/pkg/errors" @@ -309,11 +308,7 @@ func (ic *interopContext) checkHashedWitness(hash util.Uint160) (bool, error) { // checkKeyedWitness checks hash of signature check contract with a given public // key against current list of script hashes for verifying in the interop context. func (ic *interopContext) checkKeyedWitness(key *keys.PublicKey) (bool, error) { - script, err := smartcontract.CreateSignatureRedeemScript(key) - if err != nil { - return false, gherr.Wrap(err, "failed to create signature script for a key") - } - return ic.checkHashedWitness(hash.Hash160(script)) + return ic.checkHashedWitness(hash.Hash160(key.GetVerificationScript())) } // runtimeCheckWitness checks witnesses. diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index dad925ffd..debe09d1e 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -12,6 +12,7 @@ import ( "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/io" + "github.com/CityOfZion/neo-go/pkg/vm/opcode" "github.com/pkg/errors" ) @@ -222,13 +223,19 @@ func (p *PublicKey) EncodeBinary(w *io.BinWriter) { w.WriteBytes(p.Bytes()) } +// GetVerificationScript returns NEO VM bytecode with CHECKSIG command for the +// public key. +func (p *PublicKey) GetVerificationScript() []byte { + b := p.Bytes() + b = append([]byte{byte(opcode.PUSHBYTES33)}, b...) + b = append(b, byte(opcode.CHECKSIG)) + + return b +} + // Signature returns a NEO-specific hash of the key. func (p *PublicKey) Signature() []byte { - b := p.Bytes() - b = append([]byte{0x21}, b...) - b = append(b, 0xAC) - - sig := hash.Hash160(b) + sig := hash.Hash160(p.GetVerificationScript()) return sig.Bytes() } diff --git a/pkg/crypto/keys/wif.go b/pkg/crypto/keys/wif.go index 8972328cf..3e30fc47a 100644 --- a/pkg/crypto/keys/wif.go +++ b/pkg/crypto/keys/wif.go @@ -90,19 +90,3 @@ func WIFDecode(wif string, version byte) (*WIF, error) { w.Compressed = true return w, nil } - -// GetVerificationScript returns NEO VM bytecode with checksig command for the public key. -func (wif WIF) GetVerificationScript() []byte { - const ( - pushbytes33 = 0x21 - checksig = 0xac - ) - var ( - vScript []byte - pubkey *PublicKey - ) - pubkey = wif.PrivateKey.PublicKey() - vScript = append([]byte{pushbytes33}, pubkey.Bytes()...) - vScript = append(vScript, checksig) - return vScript -} diff --git a/pkg/rpc/txBuilder.go b/pkg/rpc/txBuilder.go index bd79511ef..308c2647e 100644 --- a/pkg/rpc/txBuilder.go +++ b/pkg/rpc/txBuilder.go @@ -86,7 +86,7 @@ func SignTx(tx *transaction.Transaction, wif *keys.WIF) error { if witness.InvocationScript, err = GetInvocationScript(tx, wif); err != nil { return errs.Wrap(err, "failed to create invocation script") } - witness.VerificationScript = wif.GetVerificationScript() + witness.VerificationScript = wif.PrivateKey.PublicKey().GetVerificationScript() tx.Scripts = append(tx.Scripts, &witness) tx.Hash() diff --git a/pkg/smartcontract/contract.go b/pkg/smartcontract/contract.go index 123971d32..4766659ea 100644 --- a/pkg/smartcontract/contract.go +++ b/pkg/smartcontract/contract.go @@ -10,21 +10,6 @@ import ( "github.com/CityOfZion/neo-go/pkg/vm/opcode" ) -// CreateSignatureRedeemScript creates a check signature script runnable by VM. -func CreateSignatureRedeemScript(key *keys.PublicKey) ([]byte, error) { - buf := new(bytes.Buffer) - err := vm.EmitBytes(buf, key.Bytes()) - if err != nil { - return nil, err - } - err = vm.EmitOpcode(buf, opcode.CHECKSIG) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - // CreateMultiSigRedeemScript creates a script runnable by the VM. func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, error) { if m <= 1 { From 141d27795ee0f1c2eee386d194c55f8c46666d4b Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 3 Dec 2019 17:27:35 +0300 Subject: [PATCH 3/5] rpc: remove hardcoded pushbytes64 constant Using our new and shiny opcode package. --- pkg/rpc/txBuilder.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/rpc/txBuilder.go b/pkg/rpc/txBuilder.go index 308c2647e..28c31b24b 100644 --- a/pkg/rpc/txBuilder.go +++ b/pkg/rpc/txBuilder.go @@ -95,9 +95,6 @@ func SignTx(tx *transaction.Transaction, wif *keys.WIF) error { // GetInvocationScript returns NEO VM script containing transaction signature. func GetInvocationScript(tx *transaction.Transaction, wif *keys.WIF) ([]byte, error) { - const ( - pushbytes64 = 0x40 - ) var ( err error buf = io.NewBufBinWriter() @@ -112,7 +109,7 @@ func GetInvocationScript(tx *transaction.Transaction, wif *keys.WIF) ([]byte, er if err != nil { return nil, errs.Wrap(err, "Failed ti sign transaction with private key") } - return append([]byte{pushbytes64}, signature...), nil + return append([]byte{byte(opcode.PUSHBYTES64)}, signature...), nil } // CreateDeploymentScript returns a script that deploys given smart contract From 31add423a8ee1da0d22ce93f2f45033e064ee61e Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 3 Dec 2019 17:54:47 +0300 Subject: [PATCH 4/5] core: replace open-coded PUSHBYTES64 with the one from opcode --- pkg/core/helper_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index c9aa54416..43b8d96ab 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -15,6 +15,7 @@ import ( "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/smartcontract" "github.com/CityOfZion/neo-go/pkg/util" + "github.com/CityOfZion/neo-go/pkg/vm/opcode" "github.com/stretchr/testify/require" ) @@ -84,8 +85,7 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block { if err != nil || len(sig) != 64 { panic(err) } - // 0x40 is PUSHBYTES64 - invScript = append(invScript, 0x40) + invScript = append(invScript, byte(opcode.PUSHBYTES64)) invScript = append(invScript, sig...) } b.Script.InvocationScript = invScript From 852e6a335b8c60847d29bfba36b6b33c5a96fe2c Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 3 Dec 2019 18:18:14 +0300 Subject: [PATCH 5/5] compiler: move it up from vm It really deserves it, I think. Especially given that it doesn't have any direct usage of `vm` package now. --- .gitignore | 3 --- cli/smartcontract/smart_contract.go | 2 +- docs/cli.md | 6 ++---- pkg/{vm => }/compiler/analysis.go | 0 pkg/{vm => }/compiler/codegen.go | 0 pkg/{vm => }/compiler/compiler.go | 0 pkg/{vm => }/compiler/compiler_test.go | 4 ++-- pkg/{vm => }/compiler/emit.go | 0 pkg/{vm => }/compiler/func_scope.go | 0 pkg/{vm => }/compiler/syscall.go | 0 pkg/vm/cli/cli.go | 2 +- pkg/vm/tests/vm_test.go | 2 +- 12 files changed, 7 insertions(+), 12 deletions(-) rename pkg/{vm => }/compiler/analysis.go (100%) rename pkg/{vm => }/compiler/codegen.go (100%) rename pkg/{vm => }/compiler/compiler.go (100%) rename pkg/{vm => }/compiler/compiler_test.go (90%) rename pkg/{vm => }/compiler/emit.go (100%) rename pkg/{vm => }/compiler/func_scope.go (100%) rename pkg/{vm => }/compiler/syscall.go (100%) diff --git a/.gitignore b/.gitignore index 78297164b..cb8e5a620 100644 --- a/.gitignore +++ b/.gitignore @@ -28,9 +28,6 @@ bin/ *~ TAGS -# anthdm todolists -/pkg/vm/compiler/todo.md - # leveldb chains/ chain/ diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 526ceaf6e..f80c93ce2 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -11,13 +11,13 @@ import ( "os" "path/filepath" + "github.com/CityOfZion/neo-go/pkg/compiler" "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/rpc" "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/compiler" "github.com/go-yaml/yaml" "github.com/pkg/errors" "github.com/urfave/cli" diff --git a/docs/cli.md b/docs/cli.md index 3748401aa..d8a224b88 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -166,7 +166,7 @@ INDEX OPCODE DESC ``` In depth documentation about the **neo-go** compiler and smart contract examples can be found inside -the [compiler package](https://github.com/nspcc-dev/neo-go/tree/master/pkg/vm/compiler). +the [compiler package](https://github.com/nspcc-dev/neo-go/tree/master/pkg/compiler). ## VM run To run VM use @@ -182,10 +182,8 @@ There is a small subset of commands: - `ops` -- show the opcodes of currently loaded contract - `run` -- executes currently loaded contract -More details can be found in - [vm package]([compiler package](https://github.com/nspcc-dev/neo-go/tree/master/pkg/vm/compiler)) ## Wallet operations - `./bin/neo-go wallet create -p newWallet` to create new wallet in the path `newWallet` - `./bin/neo-go wallet open -p newWallet` to open created wallet in the path `newWallet` -- `./bin/neo-go wallet create -p newWallet -a` to create new account \ No newline at end of file +- `./bin/neo-go wallet create -p newWallet -a` to create new account diff --git a/pkg/vm/compiler/analysis.go b/pkg/compiler/analysis.go similarity index 100% rename from pkg/vm/compiler/analysis.go rename to pkg/compiler/analysis.go diff --git a/pkg/vm/compiler/codegen.go b/pkg/compiler/codegen.go similarity index 100% rename from pkg/vm/compiler/codegen.go rename to pkg/compiler/codegen.go diff --git a/pkg/vm/compiler/compiler.go b/pkg/compiler/compiler.go similarity index 100% rename from pkg/vm/compiler/compiler.go rename to pkg/compiler/compiler.go diff --git a/pkg/vm/compiler/compiler_test.go b/pkg/compiler/compiler_test.go similarity index 90% rename from pkg/vm/compiler/compiler_test.go rename to pkg/compiler/compiler_test.go index 5ddd11824..e49a31f30 100644 --- a/pkg/vm/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -6,10 +6,10 @@ import ( "path" "testing" - "github.com/CityOfZion/neo-go/pkg/vm/compiler" + "github.com/CityOfZion/neo-go/pkg/compiler" ) -const examplePath = "../../../examples" +const examplePath = "../../examples" func TestExamplesFolder(t *testing.T) { infos, err := ioutil.ReadDir(examplePath) diff --git a/pkg/vm/compiler/emit.go b/pkg/compiler/emit.go similarity index 100% rename from pkg/vm/compiler/emit.go rename to pkg/compiler/emit.go diff --git a/pkg/vm/compiler/func_scope.go b/pkg/compiler/func_scope.go similarity index 100% rename from pkg/vm/compiler/func_scope.go rename to pkg/compiler/func_scope.go diff --git a/pkg/vm/compiler/syscall.go b/pkg/compiler/syscall.go similarity index 100% rename from pkg/vm/compiler/syscall.go rename to pkg/compiler/syscall.go diff --git a/pkg/vm/cli/cli.go b/pkg/vm/cli/cli.go index e4e2115ba..3054df427 100644 --- a/pkg/vm/cli/cli.go +++ b/pkg/vm/cli/cli.go @@ -10,8 +10,8 @@ import ( "strconv" "strings" + "github.com/CityOfZion/neo-go/pkg/compiler" "github.com/CityOfZion/neo-go/pkg/vm" - "github.com/CityOfZion/neo-go/pkg/vm/compiler" "gopkg.in/abiosoft/ishell.v2" ) diff --git a/pkg/vm/tests/vm_test.go b/pkg/vm/tests/vm_test.go index deb18eaa7..011103934 100644 --- a/pkg/vm/tests/vm_test.go +++ b/pkg/vm/tests/vm_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" + "github.com/CityOfZion/neo-go/pkg/compiler" "github.com/CityOfZion/neo-go/pkg/vm" - "github.com/CityOfZion/neo-go/pkg/vm/compiler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" )