mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-25 23:42:23 +00:00
emit: accept multiple opcodes in Opcode()
This commit is contained in:
parent
0e82d4cbd1
commit
b2a3a0851e
15 changed files with 145 additions and 162 deletions
|
@ -102,7 +102,7 @@ func handleCandidate(ctx *cli.Context, method string) error {
|
||||||
gas := flags.Fixed8FromContext(ctx, "gas")
|
gas := flags.Fixed8FromContext(ctx, "gas")
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, method, acc.PrivateKey().PublicKey().Bytes())
|
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, method, acc.PrivateKey().PublicKey().Bytes())
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), transaction.Signer{
|
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), transaction.Signer{
|
||||||
Account: acc.Contract.ScriptHash(),
|
Account: acc.Contract.ScriptHash(),
|
||||||
Scopes: transaction.CalledByEntry,
|
Scopes: transaction.CalledByEntry,
|
||||||
|
@ -160,7 +160,7 @@ func handleVote(ctx *cli.Context) error {
|
||||||
gas := flags.Fixed8FromContext(ctx, "gas")
|
gas := flags.Fixed8FromContext(ctx, "gas")
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, "vote", addr.BytesBE(), pubArg)
|
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, "vote", addr.BytesBE(), pubArg)
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||||
|
|
||||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), transaction.Signer{
|
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), transaction.Signer{
|
||||||
Account: acc.Contract.ScriptHash(),
|
Account: acc.Contract.ScriptHash(),
|
||||||
|
|
|
@ -176,13 +176,12 @@ func (c *codegen) emitLoadConst(t types.TypeAndValue) {
|
||||||
|
|
||||||
func (c *codegen) emitLoadField(i int) {
|
func (c *codegen) emitLoadField(i int) {
|
||||||
emit.Int(c.prog.BinWriter, int64(i))
|
emit.Int(c.prog.BinWriter, int64(i))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PICKITEM)
|
emit.Opcodes(c.prog.BinWriter, opcode.PICKITEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) emitStoreStructField(i int) {
|
func (c *codegen) emitStoreStructField(i int) {
|
||||||
emit.Int(c.prog.BinWriter, int64(i))
|
emit.Int(c.prog.BinWriter, int64(i))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ROT)
|
emit.Opcodes(c.prog.BinWriter, opcode.ROT, opcode.SETITEM)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getVarIndex returns variable type and position in corresponding slot,
|
// getVarIndex returns variable type and position in corresponding slot,
|
||||||
|
@ -226,7 +225,7 @@ func (c *codegen) emitLoadVar(pkg string, name string) {
|
||||||
func (c *codegen) emitLoadByIndex(t varType, i int) {
|
func (c *codegen) emitLoadByIndex(t varType, i int) {
|
||||||
base, _ := getBaseOpcode(t)
|
base, _ := getBaseOpcode(t)
|
||||||
if i < 7 {
|
if i < 7 {
|
||||||
emit.Opcode(c.prog.BinWriter, base+opcode.Opcode(i))
|
emit.Opcodes(c.prog.BinWriter, base+opcode.Opcode(i))
|
||||||
} else {
|
} else {
|
||||||
emit.Instruction(c.prog.BinWriter, base+7, []byte{byte(i)})
|
emit.Instruction(c.prog.BinWriter, base+7, []byte{byte(i)})
|
||||||
}
|
}
|
||||||
|
@ -235,7 +234,7 @@ func (c *codegen) emitLoadByIndex(t varType, i int) {
|
||||||
// emitStoreVar stores top value from the evaluation stack in the specified variable.
|
// emitStoreVar stores top value from the evaluation stack in the specified variable.
|
||||||
func (c *codegen) emitStoreVar(pkg string, name string) {
|
func (c *codegen) emitStoreVar(pkg string, name string) {
|
||||||
if name == "_" {
|
if name == "_" {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t, i := c.getVarIndex(pkg, name)
|
t, i := c.getVarIndex(pkg, name)
|
||||||
|
@ -246,7 +245,7 @@ func (c *codegen) emitStoreVar(pkg string, name string) {
|
||||||
func (c *codegen) emitStoreByIndex(t varType, i int) {
|
func (c *codegen) emitStoreByIndex(t varType, i int) {
|
||||||
_, base := getBaseOpcode(t)
|
_, base := getBaseOpcode(t)
|
||||||
if i < 7 {
|
if i < 7 {
|
||||||
emit.Opcode(c.prog.BinWriter, base+opcode.Opcode(i))
|
emit.Opcodes(c.prog.BinWriter, base+opcode.Opcode(i))
|
||||||
} else {
|
} else {
|
||||||
emit.Instruction(c.prog.BinWriter, base+7, []byte{byte(i)})
|
emit.Instruction(c.prog.BinWriter, base+7, []byte{byte(i)})
|
||||||
}
|
}
|
||||||
|
@ -264,20 +263,20 @@ func (c *codegen) emitDefault(t types.Type) {
|
||||||
case info&types.IsBoolean != 0:
|
case info&types.IsBoolean != 0:
|
||||||
emit.Bool(c.prog.BinWriter, false)
|
emit.Bool(c.prog.BinWriter, false)
|
||||||
default:
|
default:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSHNULL)
|
emit.Opcodes(c.prog.BinWriter, opcode.PUSHNULL)
|
||||||
}
|
}
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
num := t.NumFields()
|
num := t.NumFields()
|
||||||
emit.Int(c.prog.BinWriter, int64(num))
|
emit.Int(c.prog.BinWriter, int64(num))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWSTRUCT)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEWSTRUCT)
|
||||||
for i := 0; i < num; i++ {
|
for i := 0; i < num; i++ {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
emit.Int(c.prog.BinWriter, int64(i))
|
emit.Int(c.prog.BinWriter, int64(i))
|
||||||
c.emitDefault(t.Field(i).Type())
|
c.emitDefault(t.Field(i).Type())
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
emit.Opcodes(c.prog.BinWriter, opcode.SETITEM)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSHNULL)
|
emit.Opcodes(c.prog.BinWriter, opcode.PUSHNULL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +388,7 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl, pkg *types.
|
||||||
// This can be the case with void and named-return functions.
|
// This can be the case with void and named-return functions.
|
||||||
if !isInit && !lastStmtIsReturn(decl) {
|
if !isInit && !lastStmtIsReturn(decl) {
|
||||||
c.saveSequencePoint(decl.Body)
|
c.saveSequencePoint(decl.Body)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.RET)
|
emit.Opcodes(c.prog.BinWriter, opcode.RET)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.rng.End = uint16(c.prog.Len() - 1)
|
f.rng.End = uint16(c.prog.Len() - 1)
|
||||||
|
@ -510,8 +509,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
}
|
}
|
||||||
ast.Walk(c, t.X)
|
ast.Walk(c, t.X)
|
||||||
ast.Walk(c, t.Index)
|
ast.Walk(c, t.Index)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ROT)
|
emit.Opcodes(c.prog.BinWriter, opcode.ROT, opcode.SETITEM)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -527,19 +525,16 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
if n.Low != nil {
|
if n.Low != nil {
|
||||||
ast.Walk(c, n.Low)
|
ast.Walk(c, n.Low)
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSH0)
|
emit.Opcodes(c.prog.BinWriter, opcode.PUSH0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.High != nil {
|
if n.High != nil {
|
||||||
ast.Walk(c, n.High)
|
ast.Walk(c, n.High)
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.OVER)
|
emit.Opcodes(c.prog.BinWriter, opcode.OVER, opcode.SIZE)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SIZE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.OVER)
|
emit.Opcodes(c.prog.BinWriter, opcode.OVER, opcode.SUB, opcode.SUBSTR)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SUB)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SUBSTR)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -574,7 +569,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
c.processDefers()
|
c.processDefers()
|
||||||
|
|
||||||
c.saveSequencePoint(n)
|
c.saveSequencePoint(n)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.RET)
|
emit.Opcodes(c.prog.BinWriter, opcode.RET)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *ast.IfStmt:
|
case *ast.IfStmt:
|
||||||
|
@ -630,9 +625,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
|
|
||||||
if l := len(cc.List); l != 0 { // if not `default`
|
if l := len(cc.List); l != 0 { // if not `default`
|
||||||
for j := range cc.List {
|
for j := range cc.List {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
ast.Walk(c, cc.List[j])
|
ast.Walk(c, cc.List[j])
|
||||||
emit.Opcode(c.prog.BinWriter, eqOpcode)
|
emit.Opcodes(c.prog.BinWriter, eqOpcode)
|
||||||
if j == l-1 {
|
if j == l-1 {
|
||||||
emit.Jmp(c.prog.BinWriter, opcode.JMPIFNOTL, lEnd)
|
emit.Jmp(c.prog.BinWriter, opcode.JMPIFNOTL, lEnd)
|
||||||
} else {
|
} else {
|
||||||
|
@ -691,7 +686,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
if tv := c.typeAndValueOf(n); tv.Value != nil {
|
if tv := c.typeAndValueOf(n); tv.Value != nil {
|
||||||
c.emitLoadConst(tv)
|
c.emitLoadConst(tv)
|
||||||
} else if n.Name == "nil" {
|
} else if n.Name == "nil" {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSHNULL)
|
emit.Opcodes(c.prog.BinWriter, opcode.PUSHNULL)
|
||||||
} else {
|
} else {
|
||||||
c.emitLoadVar("", n.Name)
|
c.emitLoadVar("", n.Name)
|
||||||
}
|
}
|
||||||
|
@ -714,7 +709,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
ast.Walk(c, n.Elts[i])
|
ast.Walk(c, n.Elts[i])
|
||||||
}
|
}
|
||||||
emit.Int(c.prog.BinWriter, int64(ln))
|
emit.Int(c.prog.BinWriter, int64(ln))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PACK)
|
emit.Opcodes(c.prog.BinWriter, opcode.PACK)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -786,12 +781,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
if ok && !isInteropPath(typ.String()) {
|
if ok && !isInteropPath(typ.String()) {
|
||||||
// To clone struct fields we create a new array and append struct to it.
|
// To clone struct fields we create a new array and append struct to it.
|
||||||
// This way even non-pointer struct fields will be copied.
|
// This way even non-pointer struct fields will be copied.
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWARRAY0)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEWARRAY0,
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
opcode.DUP, opcode.ROT, opcode.APPEND,
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ROT)
|
opcode.PUSH0, opcode.PICKITEM)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.APPEND)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSH0)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PICKITEM)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Do not swap for builtin functions.
|
// Do not swap for builtin functions.
|
||||||
|
@ -802,7 +794,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
varSize := len(n.Args) - typ.Params().Len() + 1
|
varSize := len(n.Args) - typ.Params().Len() + 1
|
||||||
c.emitReverse(varSize)
|
c.emitReverse(varSize)
|
||||||
emit.Int(c.prog.BinWriter, int64(varSize))
|
emit.Int(c.prog.BinWriter, int64(varSize))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PACK)
|
emit.Opcodes(c.prog.BinWriter, opcode.PACK)
|
||||||
numArgs -= varSize - 1
|
numArgs -= varSize - 1
|
||||||
}
|
}
|
||||||
c.emitReverse(numArgs)
|
c.emitReverse(numArgs)
|
||||||
|
@ -822,11 +814,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
c.emitConvert(stackitem.ByteArrayT)
|
c.emitConvert(stackitem.ByteArrayT)
|
||||||
} else if isFunc {
|
} else if isFunc {
|
||||||
c.emitLoadVar("", name)
|
c.emitLoadVar("", name)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.CALLA)
|
emit.Opcodes(c.prog.BinWriter, opcode.CALLA)
|
||||||
}
|
}
|
||||||
case isLiteral:
|
case isLiteral:
|
||||||
ast.Walk(c, n.Fun)
|
ast.Walk(c, n.Fun)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.CALLA)
|
emit.Opcodes(c.prog.BinWriter, opcode.CALLA)
|
||||||
case isSyscall(f):
|
case isSyscall(f):
|
||||||
c.convertSyscall(n, f.pkg.Name(), f.name)
|
c.convertSyscall(n, f.pkg.Name(), f.name)
|
||||||
default:
|
default:
|
||||||
|
@ -843,7 +835,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
sz = f.Results().Len()
|
sz = f.Results().Len()
|
||||||
}
|
}
|
||||||
for i := 0; i < sz; i++ {
|
for i := 0; i < sz; i++ {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,11 +901,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
case token.ADD:
|
case token.ADD:
|
||||||
// +10 == 10, no need to do anything in this case
|
// +10 == 10, no need to do anything in this case
|
||||||
case token.SUB:
|
case token.SUB:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEGATE)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEGATE)
|
||||||
case token.NOT:
|
case token.NOT:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NOT)
|
emit.Opcodes(c.prog.BinWriter, opcode.NOT)
|
||||||
case token.XOR:
|
case token.XOR:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.INVERT)
|
emit.Opcodes(c.prog.BinWriter, opcode.INVERT)
|
||||||
default:
|
default:
|
||||||
c.prog.Err = fmt.Errorf("invalid unary operator: %s", n.Op)
|
c.prog.Err = fmt.Errorf("invalid unary operator: %s", n.Op)
|
||||||
return nil
|
return nil
|
||||||
|
@ -937,7 +929,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
// This will load local whatever X is.
|
// This will load local whatever X is.
|
||||||
ast.Walk(c, n.X)
|
ast.Walk(c, n.X)
|
||||||
ast.Walk(c, n.Index)
|
ast.Walk(c, n.Index)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PICKITEM) // just pickitem here
|
emit.Opcodes(c.prog.BinWriter, opcode.PICKITEM) // just pickitem here
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -1049,13 +1041,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
// For slices we iterate index from 0 to len-1, storing array, len and index on stack.
|
// For slices we iterate index from 0 to len-1, storing array, len and index on stack.
|
||||||
// For maps we iterate index from 0 to len-1, storing map, keyarray, size and index on stack.
|
// For maps we iterate index from 0 to len-1, storing map, keyarray, size and index on stack.
|
||||||
_, isMap := c.typeOf(n.X).Underlying().(*types.Map)
|
_, isMap := c.typeOf(n.X).Underlying().(*types.Map)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
if isMap {
|
if isMap {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.KEYS)
|
emit.Opcodes(c.prog.BinWriter, opcode.KEYS, opcode.DUP)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
|
||||||
}
|
}
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SIZE)
|
emit.Opcodes(c.prog.BinWriter, opcode.SIZE, opcode.PUSH0)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSH0)
|
|
||||||
|
|
||||||
stackSize := 3 // slice, len(slice), index
|
stackSize := 3 // slice, len(slice), index
|
||||||
if isMap {
|
if isMap {
|
||||||
|
@ -1064,8 +1054,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
c.pushStackLabel(label, stackSize)
|
c.pushStackLabel(label, stackSize)
|
||||||
c.setLabel(start)
|
c.setLabel(start)
|
||||||
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.OVER)
|
emit.Opcodes(c.prog.BinWriter, opcode.OVER, opcode.OVER)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.OVER)
|
|
||||||
emit.Jmp(c.prog.BinWriter, opcode.JMPLEL, end)
|
emit.Jmp(c.prog.BinWriter, opcode.JMPLEL, end)
|
||||||
|
|
||||||
var keyLoaded bool
|
var keyLoaded bool
|
||||||
|
@ -1074,11 +1063,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
if isMap {
|
if isMap {
|
||||||
c.rangeLoadKey()
|
c.rangeLoadKey()
|
||||||
if needValue {
|
if needValue {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
keyLoaded = true
|
keyLoaded = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
}
|
}
|
||||||
c.emitStoreVar("", n.Key.(*ast.Ident).Name)
|
c.emitStoreVar("", n.Key.(*ast.Ident).Name)
|
||||||
}
|
}
|
||||||
|
@ -1089,9 +1078,10 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
if isMap {
|
if isMap {
|
||||||
// we have loaded only key from key array, now load value
|
// we have loaded only key from key array, now load value
|
||||||
emit.Int(c.prog.BinWriter, 4)
|
emit.Int(c.prog.BinWriter, 4)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PICK) // load map itself (+1 because key was pushed)
|
emit.Opcodes(c.prog.BinWriter,
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SWAP) // key should be on top
|
opcode.PICK, // load map itself (+1 because key was pushed)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PICKITEM)
|
opcode.SWAP, // key should be on top
|
||||||
|
opcode.PICKITEM)
|
||||||
}
|
}
|
||||||
c.emitStoreVar("", n.Value.(*ast.Ident).Name)
|
c.emitStoreVar("", n.Value.(*ast.Ident).Name)
|
||||||
}
|
}
|
||||||
|
@ -1100,7 +1090,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
|
|
||||||
c.setLabel(post)
|
c.setLabel(post)
|
||||||
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.INC)
|
emit.Opcodes(c.prog.BinWriter, opcode.INC)
|
||||||
emit.Jmp(c.prog.BinWriter, opcode.JMPL, start)
|
emit.Jmp(c.prog.BinWriter, opcode.JMPL, start)
|
||||||
|
|
||||||
c.setLabel(end)
|
c.setLabel(end)
|
||||||
|
@ -1164,16 +1154,17 @@ func (c *codegen) processDefers() {
|
||||||
c.setLabel(before)
|
c.setLabel(before)
|
||||||
emit.Int(c.prog.BinWriter, 0)
|
emit.Int(c.prog.BinWriter, 0)
|
||||||
c.emitStoreByIndex(varLocal, c.scope.finallyProcessedIndex)
|
c.emitStoreByIndex(varLocal, c.scope.finallyProcessedIndex)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ENDFINALLY)
|
emit.Opcodes(c.prog.BinWriter, opcode.ENDFINALLY)
|
||||||
c.setLabel(after)
|
c.setLabel(after)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) rangeLoadKey() {
|
func (c *codegen) rangeLoadKey() {
|
||||||
emit.Int(c.prog.BinWriter, 2)
|
emit.Int(c.prog.BinWriter, 2)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PICK) // load keys
|
emit.Opcodes(c.prog.BinWriter,
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.OVER) // load index in key array
|
opcode.PICK, // load keys
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PICKITEM)
|
opcode.OVER, // load index in key array
|
||||||
|
opcode.PICKITEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isFallthroughStmt(c ast.Node) bool {
|
func isFallthroughStmt(c ast.Node) bool {
|
||||||
|
@ -1230,11 +1221,11 @@ func (c *codegen) emitBinaryExpr(n *ast.BinaryExpr, needJump bool, cond bool, jm
|
||||||
return
|
return
|
||||||
} else if arg := c.getCompareWithNilArg(n); arg != nil {
|
} else if arg := c.getCompareWithNilArg(n); arg != nil {
|
||||||
ast.Walk(c, arg)
|
ast.Walk(c, arg)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ISNULL)
|
emit.Opcodes(c.prog.BinWriter, opcode.ISNULL)
|
||||||
if needJump {
|
if needJump {
|
||||||
c.emitJumpOnCondition(cond == (n.Op == token.EQL), jmpLabel)
|
c.emitJumpOnCondition(cond == (n.Op == token.EQL), jmpLabel)
|
||||||
} else if n.Op == token.NEQ {
|
} else if n.Op == token.NEQ {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NOT)
|
emit.Opcodes(c.prog.BinWriter, opcode.NOT)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1299,14 +1290,13 @@ func (c *codegen) dropStackLabel() {
|
||||||
func (c *codegen) dropItems(n int) {
|
func (c *codegen) dropItems(n int) {
|
||||||
if n < 4 {
|
if n < 4 {
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
emit.Int(c.prog.BinWriter, int64(n))
|
emit.Int(c.prog.BinWriter, int64(n))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PACK)
|
emit.Opcodes(c.prog.BinWriter, opcode.PACK, opcode.DROP)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitReverse reverses top num items of the stack.
|
// emitReverse reverses top num items of the stack.
|
||||||
|
@ -1314,14 +1304,14 @@ func (c *codegen) emitReverse(num int) {
|
||||||
switch num {
|
switch num {
|
||||||
case 0, 1:
|
case 0, 1:
|
||||||
case 2:
|
case 2:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SWAP)
|
emit.Opcodes(c.prog.BinWriter, opcode.SWAP)
|
||||||
case 3:
|
case 3:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.REVERSE3)
|
emit.Opcodes(c.prog.BinWriter, opcode.REVERSE3)
|
||||||
case 4:
|
case 4:
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.REVERSE4)
|
emit.Opcodes(c.prog.BinWriter, opcode.REVERSE4)
|
||||||
default:
|
default:
|
||||||
emit.Int(c.prog.BinWriter, int64(num))
|
emit.Int(c.prog.BinWriter, int64(num))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.REVERSEN)
|
emit.Opcodes(c.prog.BinWriter, opcode.REVERSEN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,7 +1390,7 @@ func (c *codegen) convertSyscall(expr *ast.CallExpr, api, name string) {
|
||||||
|
|
||||||
// This NOP instruction is basically not needed, but if we do, we have a
|
// 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.
|
// one to one matching avm file with neo-python which is very nice for debugging.
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NOP)
|
emit.Opcodes(c.prog.BinWriter, opcode.NOP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitSliceHelper emits 3 items on stack: slice, its first index, and its size.
|
// emitSliceHelper emits 3 items on stack: slice, its first index, and its size.
|
||||||
|
@ -1416,8 +1406,7 @@ func (c *codegen) emitSliceHelper(e ast.Expr) {
|
||||||
if src.High != nil {
|
if src.High != nil {
|
||||||
ast.Walk(c, src.High)
|
ast.Walk(c, src.High)
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP, opcode.SIZE)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SIZE)
|
|
||||||
}
|
}
|
||||||
if src.Low != nil {
|
if src.Low != nil {
|
||||||
ast.Walk(c, src.Low)
|
ast.Walk(c, src.Low)
|
||||||
|
@ -1427,17 +1416,13 @@ func (c *codegen) emitSliceHelper(e ast.Expr) {
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ast.Walk(c, src)
|
ast.Walk(c, src)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP, opcode.SIZE)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SIZE)
|
|
||||||
emit.Int(c.prog.BinWriter, 0)
|
emit.Int(c.prog.BinWriter, 0)
|
||||||
}
|
}
|
||||||
if !hasLowIndex {
|
if !hasLowIndex {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SWAP)
|
emit.Opcodes(c.prog.BinWriter, opcode.SWAP)
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP, opcode.ROT, opcode.SWAP, opcode.SUB)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ROT)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SWAP)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SUB)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1456,22 +1441,21 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
c.emitSliceHelper(expr.Args[0])
|
c.emitSliceHelper(expr.Args[0])
|
||||||
c.emitSliceHelper(expr.Args[1])
|
c.emitSliceHelper(expr.Args[1])
|
||||||
emit.Int(c.prog.BinWriter, 3)
|
emit.Int(c.prog.BinWriter, 3)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ROLL)
|
emit.Opcodes(c.prog.BinWriter, opcode.ROLL, opcode.MIN)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.MIN)
|
|
||||||
if !c.scope.voidCalls[expr] {
|
if !c.scope.voidCalls[expr] {
|
||||||
// insert top item to the bottom of MEMCPY args, so that it is left on stack
|
// insert top item to the bottom of MEMCPY args, so that it is left on stack
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
emit.Int(c.prog.BinWriter, 6)
|
emit.Int(c.prog.BinWriter, 6)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.REVERSEN)
|
emit.Opcodes(c.prog.BinWriter, opcode.REVERSEN)
|
||||||
emit.Int(c.prog.BinWriter, 5)
|
emit.Int(c.prog.BinWriter, 5)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.REVERSEN)
|
emit.Opcodes(c.prog.BinWriter, opcode.REVERSEN)
|
||||||
}
|
}
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.MEMCPY)
|
emit.Opcodes(c.prog.BinWriter, opcode.MEMCPY)
|
||||||
case "make":
|
case "make":
|
||||||
typ := c.typeOf(expr.Args[0])
|
typ := c.typeOf(expr.Args[0])
|
||||||
switch {
|
switch {
|
||||||
case isMap(typ):
|
case isMap(typ):
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWMAP)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEWMAP)
|
||||||
default:
|
default:
|
||||||
if len(expr.Args) == 3 {
|
if len(expr.Args) == 3 {
|
||||||
c.prog.Err = fmt.Errorf("`make()` with a capacity argument is not supported")
|
c.prog.Err = fmt.Errorf("`make()` with a capacity argument is not supported")
|
||||||
|
@ -1479,57 +1463,47 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
}
|
}
|
||||||
ast.Walk(c, expr.Args[1])
|
ast.Walk(c, expr.Args[1])
|
||||||
if isByteSlice(typ) {
|
if isByteSlice(typ) {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWBUFFER)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEWBUFFER)
|
||||||
} else {
|
} else {
|
||||||
neoT := toNeoType(typ.(*types.Slice).Elem())
|
neoT := toNeoType(typ.(*types.Slice).Elem())
|
||||||
emit.Instruction(c.prog.BinWriter, opcode.NEWARRAYT, []byte{byte(neoT)})
|
emit.Instruction(c.prog.BinWriter, opcode.NEWARRAYT, []byte{byte(neoT)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "len":
|
case "len":
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP, opcode.ISNULL)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ISNULL)
|
|
||||||
emit.Instruction(c.prog.BinWriter, opcode.JMPIF, []byte{2 + 1 + 2})
|
emit.Instruction(c.prog.BinWriter, opcode.JMPIF, []byte{2 + 1 + 2})
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SIZE)
|
emit.Opcodes(c.prog.BinWriter, opcode.SIZE)
|
||||||
emit.Instruction(c.prog.BinWriter, opcode.JMP, []byte{2 + 1 + 1})
|
emit.Instruction(c.prog.BinWriter, opcode.JMP, []byte{2 + 1 + 1})
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP, opcode.PUSH0)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSH0)
|
|
||||||
case "append":
|
case "append":
|
||||||
arg := expr.Args[0]
|
arg := expr.Args[0]
|
||||||
typ := c.typeInfo.Types[arg].Type
|
typ := c.typeInfo.Types[arg].Type
|
||||||
c.emitReverse(len(expr.Args))
|
c.emitReverse(len(expr.Args))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP, opcode.ISNULL)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ISNULL)
|
|
||||||
emit.Instruction(c.prog.BinWriter, opcode.JMPIFNOT, []byte{2 + 3})
|
emit.Instruction(c.prog.BinWriter, opcode.JMPIFNOT, []byte{2 + 3})
|
||||||
if isByteSlice(typ) {
|
if isByteSlice(typ) {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP, opcode.PUSH0, opcode.NEWBUFFER)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSH0)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWBUFFER)
|
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP, opcode.NEWARRAY0, opcode.NOP)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWARRAY0)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NOP)
|
|
||||||
}
|
}
|
||||||
// Jump target.
|
// Jump target.
|
||||||
for range expr.Args[1:] {
|
for range expr.Args[1:] {
|
||||||
if isByteSlice(typ) {
|
if isByteSlice(typ) {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SWAP)
|
emit.Opcodes(c.prog.BinWriter, opcode.SWAP, opcode.CAT)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.CAT)
|
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP, opcode.ROT, opcode.APPEND)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ROT)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.APPEND)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "panic":
|
case "panic":
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.THROW)
|
emit.Opcodes(c.prog.BinWriter, opcode.THROW)
|
||||||
case "recover":
|
case "recover":
|
||||||
if !c.scope.voidCalls[expr] {
|
if !c.scope.voidCalls[expr] {
|
||||||
c.emitLoadByIndex(varGlobal, c.exceptionIndex)
|
c.emitLoadByIndex(varGlobal, c.exceptionIndex)
|
||||||
}
|
}
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.PUSHNULL)
|
emit.Opcodes(c.prog.BinWriter, opcode.PUSHNULL)
|
||||||
c.emitStoreByIndex(varGlobal, c.exceptionIndex)
|
c.emitStoreByIndex(varGlobal, c.exceptionIndex)
|
||||||
case "delete":
|
case "delete":
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.REMOVE)
|
emit.Opcodes(c.prog.BinWriter, opcode.REMOVE)
|
||||||
case "ToInteger", "ToByteArray", "ToBool":
|
case "ToInteger", "ToByteArray", "ToBool":
|
||||||
typ := stackitem.IntegerT
|
typ := stackitem.IntegerT
|
||||||
switch name {
|
switch name {
|
||||||
|
@ -1544,9 +1518,9 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
c.prog.Err = errors.New("`Remove` supports only non-byte slices")
|
c.prog.Err = errors.New("`Remove` supports only non-byte slices")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.REMOVE)
|
emit.Opcodes(c.prog.BinWriter, opcode.REMOVE)
|
||||||
case "Equals":
|
case "Equals":
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.EQUAL)
|
emit.Opcodes(c.prog.BinWriter, opcode.EQUAL)
|
||||||
case "FromAddress":
|
case "FromAddress":
|
||||||
// We can be sure that this is a ast.BasicLit just containing a simple
|
// 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
|
// address string. Note that the string returned from calling Value will
|
||||||
|
@ -1607,21 +1581,21 @@ func (c *codegen) convertByteArray(lit *ast.CompositeLit) {
|
||||||
emit.Bytes(c.prog.BinWriter, buf)
|
emit.Bytes(c.prog.BinWriter, buf)
|
||||||
c.emitConvert(stackitem.BufferT)
|
c.emitConvert(stackitem.BufferT)
|
||||||
for _, i := range varIndices {
|
for _, i := range varIndices {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
emit.Int(c.prog.BinWriter, int64(i))
|
emit.Int(c.prog.BinWriter, int64(i))
|
||||||
ast.Walk(c, lit.Elts[i])
|
ast.Walk(c, lit.Elts[i])
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
emit.Opcodes(c.prog.BinWriter, opcode.SETITEM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) convertMap(lit *ast.CompositeLit) {
|
func (c *codegen) convertMap(lit *ast.CompositeLit) {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWMAP)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEWMAP)
|
||||||
for i := range lit.Elts {
|
for i := range lit.Elts {
|
||||||
elem := lit.Elts[i].(*ast.KeyValueExpr)
|
elem := lit.Elts[i].(*ast.KeyValueExpr)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
ast.Walk(c, elem.Key)
|
ast.Walk(c, elem.Key)
|
||||||
ast.Walk(c, elem.Value)
|
ast.Walk(c, elem.Value)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
emit.Opcodes(c.prog.BinWriter, opcode.SETITEM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1646,12 +1620,12 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit, ptr bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NOP)
|
emit.Opcodes(c.prog.BinWriter, opcode.NOP)
|
||||||
emit.Int(c.prog.BinWriter, int64(strct.NumFields()))
|
emit.Int(c.prog.BinWriter, int64(strct.NumFields()))
|
||||||
if ptr {
|
if ptr {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWARRAY)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEWARRAY)
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWSTRUCT)
|
emit.Opcodes(c.prog.BinWriter, opcode.NEWSTRUCT)
|
||||||
}
|
}
|
||||||
|
|
||||||
keyedLit := len(lit.Elts) > 0
|
keyedLit := len(lit.Elts) > 0
|
||||||
|
@ -1665,7 +1639,7 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit, ptr bool) {
|
||||||
sField := strct.Field(i)
|
sField := strct.Field(i)
|
||||||
var initialized bool
|
var initialized bool
|
||||||
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||||
emit.Int(c.prog.BinWriter, int64(i))
|
emit.Int(c.prog.BinWriter, int64(i))
|
||||||
|
|
||||||
if !keyedLit {
|
if !keyedLit {
|
||||||
|
@ -1689,7 +1663,7 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit, ptr bool) {
|
||||||
if !initialized {
|
if !initialized {
|
||||||
c.emitDefault(sField.Type())
|
c.emitDefault(sField.Type())
|
||||||
}
|
}
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
emit.Opcodes(c.prog.BinWriter, opcode.SETITEM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1699,7 +1673,7 @@ func (c *codegen) emitToken(tok token.Token, typ types.Type) {
|
||||||
c.prog.Err = err
|
c.prog.Err = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
emit.Opcode(c.prog.BinWriter, op)
|
emit.Opcodes(c.prog.BinWriter, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertToken(tok token.Token, typ types.Type) (opcode.Opcode, error) {
|
func convertToken(tok token.Token, typ types.Type) (opcode.Opcode, error) {
|
||||||
|
@ -1805,7 +1779,7 @@ func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error {
|
||||||
|
|
||||||
n, hasInit := c.traverseGlobals()
|
n, hasInit := c.traverseGlobals()
|
||||||
if n > 0 || hasInit {
|
if n > 0 || hasInit {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.RET)
|
emit.Opcodes(c.prog.BinWriter, opcode.RET)
|
||||||
c.initEndOffset = c.prog.Len()
|
c.initEndOffset = c.prog.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -237,12 +237,12 @@ func TestVerifyTx(t *testing.T) {
|
||||||
}
|
}
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, sc, "transfer",
|
emit.AppCallWithOperationAndArgs(w.BinWriter, sc, "transfer",
|
||||||
neoOwner, a.Contract.ScriptHash(), amount)
|
neoOwner, a.Contract.ScriptHash(), amount)
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, gasHash, "transfer",
|
emit.AppCallWithOperationAndArgs(w.BinWriter, gasHash, "transfer",
|
||||||
neoOwner, testchain.CommitteeScriptHash(), int64(1_000_000_000))
|
neoOwner, testchain.CommitteeScriptHash(), int64(1_000_000_000))
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||||
require.NoError(t, w.Err)
|
require.NoError(t, w.Err)
|
||||||
|
|
||||||
txMove := bc.newTestTx(neoOwner, w.Bytes())
|
txMove := bc.newTestTx(neoOwner, w.Bytes())
|
||||||
|
@ -782,7 +782,7 @@ func TestSubscriptions(t *testing.T) {
|
||||||
script = io.NewBufBinWriter()
|
script = io.NewBufBinWriter()
|
||||||
emit.Bytes(script.BinWriter, []byte("nay!"))
|
emit.Bytes(script.BinWriter, []byte("nay!"))
|
||||||
emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify)
|
emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify)
|
||||||
emit.Opcode(script.BinWriter, opcode.THROW)
|
emit.Opcodes(script.BinWriter, opcode.THROW)
|
||||||
require.NoError(t, script.Err)
|
require.NoError(t, script.Err)
|
||||||
txBad := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
|
txBad := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
|
||||||
txBad.Signers = []transaction.Signer{{Account: neoOwner}}
|
txBad.Signers = []transaction.Signer{{Account: neoOwner}}
|
||||||
|
|
|
@ -361,7 +361,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Transaction {
|
func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Transaction {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, sc, "transfer", from, to, amount)
|
emit.AppCallWithOperationAndArgs(w.BinWriter, sc, "transfer", from, to, amount)
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||||
|
|
||||||
script := w.Bytes()
|
script := w.Bytes()
|
||||||
return transaction.New(testchain.Network(), script, 10000000)
|
return transaction.New(testchain.Network(), script, 10000000)
|
||||||
|
|
|
@ -83,10 +83,10 @@ func (cs *Contracts) GetPersistScript() []byte {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
emit.Int(w.BinWriter, 0)
|
emit.Int(w.BinWriter, 0)
|
||||||
emit.Opcode(w.BinWriter, opcode.NEWARRAY)
|
emit.Opcodes(w.BinWriter, opcode.NEWARRAY)
|
||||||
emit.String(w.BinWriter, "onPersist")
|
emit.String(w.BinWriter, "onPersist")
|
||||||
emit.AppCall(w.BinWriter, md.Hash)
|
emit.AppCall(w.BinWriter, md.Hash)
|
||||||
emit.Opcode(w.BinWriter, opcode.DROP)
|
emit.Opcodes(w.BinWriter, opcode.DROP)
|
||||||
}
|
}
|
||||||
cs.persistScript = w.Bytes()
|
cs.persistScript = w.Bytes()
|
||||||
return cs.persistScript
|
return cs.persistScript
|
||||||
|
@ -106,10 +106,10 @@ func (cs *Contracts) GetPostPersistScript() []byte {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
emit.Int(w.BinWriter, 0)
|
emit.Int(w.BinWriter, 0)
|
||||||
emit.Opcode(w.BinWriter, opcode.NEWARRAY)
|
emit.Opcodes(w.BinWriter, opcode.NEWARRAY)
|
||||||
emit.String(w.BinWriter, "postPersist")
|
emit.String(w.BinWriter, "postPersist")
|
||||||
emit.AppCall(w.BinWriter, md.Hash)
|
emit.AppCall(w.BinWriter, md.Hash)
|
||||||
emit.Opcode(w.BinWriter, opcode.DROP)
|
emit.Opcodes(w.BinWriter, opcode.DROP)
|
||||||
}
|
}
|
||||||
cs.postPersistScript = w.Bytes()
|
cs.postPersistScript = w.Bytes()
|
||||||
return cs.postPersistScript
|
return cs.postPersistScript
|
||||||
|
|
|
@ -56,7 +56,7 @@ func init() {
|
||||||
|
|
||||||
w.Reset()
|
w.Reset()
|
||||||
emit.Int(w.BinWriter, 0)
|
emit.Int(w.BinWriter, 0)
|
||||||
emit.Opcode(w.BinWriter, opcode.NEWARRAY)
|
emit.Opcodes(w.BinWriter, opcode.NEWARRAY)
|
||||||
emit.String(w.BinWriter, "finish")
|
emit.String(w.BinWriter, "finish")
|
||||||
emit.Bytes(w.BinWriter, h.BytesBE())
|
emit.Bytes(w.BinWriter, h.BytesBE())
|
||||||
emit.Syscall(w.BinWriter, interopnames.SystemContractCall)
|
emit.Syscall(w.BinWriter, interopnames.SystemContractCall)
|
||||||
|
|
|
@ -23,10 +23,10 @@ func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r native.Role, nodes
|
||||||
emit.Bytes(w.BinWriter, pub.Bytes())
|
emit.Bytes(w.BinWriter, pub.Bytes())
|
||||||
}
|
}
|
||||||
emit.Int(w.BinWriter, int64(len(nodes)))
|
emit.Int(w.BinWriter, int64(len(nodes)))
|
||||||
emit.Opcode(w.BinWriter, opcode.PACK)
|
emit.Opcodes(w.BinWriter, opcode.PACK)
|
||||||
emit.Int(w.BinWriter, int64(r))
|
emit.Int(w.BinWriter, int64(r))
|
||||||
emit.Int(w.BinWriter, 2)
|
emit.Int(w.BinWriter, 2)
|
||||||
emit.Opcode(w.BinWriter, opcode.PACK)
|
emit.Opcodes(w.BinWriter, opcode.PACK)
|
||||||
emit.String(w.BinWriter, "designateAsRole")
|
emit.String(w.BinWriter, "designateAsRole")
|
||||||
emit.AppCall(w.BinWriter, bc.contracts.Designate.Hash)
|
emit.AppCall(w.BinWriter, bc.contracts.Designate.Hash)
|
||||||
require.NoError(t, w.Err)
|
require.NoError(t, w.Err)
|
||||||
|
|
|
@ -27,26 +27,26 @@ import (
|
||||||
func getOracleContractState(h util.Uint160) *state.Contract {
|
func getOracleContractState(h util.Uint160) *state.Contract {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.Int(w.BinWriter, 5)
|
emit.Int(w.BinWriter, 5)
|
||||||
emit.Opcode(w.BinWriter, opcode.PACK)
|
emit.Opcodes(w.BinWriter, opcode.PACK)
|
||||||
emit.String(w.BinWriter, "request")
|
emit.String(w.BinWriter, "request")
|
||||||
emit.Bytes(w.BinWriter, h.BytesBE())
|
emit.Bytes(w.BinWriter, h.BytesBE())
|
||||||
emit.Syscall(w.BinWriter, interopnames.SystemContractCall)
|
emit.Syscall(w.BinWriter, interopnames.SystemContractCall)
|
||||||
emit.Opcode(w.BinWriter, opcode.RET)
|
emit.Opcodes(w.BinWriter, opcode.RET)
|
||||||
|
|
||||||
// `handle` method aborts if len(userData) == 2
|
// `handle` method aborts if len(userData) == 2
|
||||||
offset := w.Len()
|
offset := w.Len()
|
||||||
emit.Opcode(w.BinWriter, opcode.OVER)
|
emit.Opcodes(w.BinWriter, opcode.OVER)
|
||||||
emit.Opcode(w.BinWriter, opcode.SIZE)
|
emit.Opcodes(w.BinWriter, opcode.SIZE)
|
||||||
emit.Int(w.BinWriter, 2)
|
emit.Int(w.BinWriter, 2)
|
||||||
emit.Instruction(w.BinWriter, opcode.JMPNE, []byte{3})
|
emit.Instruction(w.BinWriter, opcode.JMPNE, []byte{3})
|
||||||
emit.Opcode(w.BinWriter, opcode.ABORT)
|
emit.Opcodes(w.BinWriter, opcode.ABORT)
|
||||||
emit.Int(w.BinWriter, 4) // url, userData, code, result
|
emit.Int(w.BinWriter, 4) // url, userData, code, result
|
||||||
emit.Opcode(w.BinWriter, opcode.PACK)
|
emit.Opcodes(w.BinWriter, opcode.PACK)
|
||||||
emit.Syscall(w.BinWriter, interopnames.SystemBinarySerialize)
|
emit.Syscall(w.BinWriter, interopnames.SystemBinarySerialize)
|
||||||
emit.String(w.BinWriter, "lastOracleResponse")
|
emit.String(w.BinWriter, "lastOracleResponse")
|
||||||
emit.Syscall(w.BinWriter, interopnames.SystemStorageGetContext)
|
emit.Syscall(w.BinWriter, interopnames.SystemStorageGetContext)
|
||||||
emit.Syscall(w.BinWriter, interopnames.SystemStoragePut)
|
emit.Syscall(w.BinWriter, interopnames.SystemStoragePut)
|
||||||
emit.Opcode(w.BinWriter, opcode.RET)
|
emit.Opcodes(w.BinWriter, opcode.RET)
|
||||||
|
|
||||||
m := manifest.NewManifest(h)
|
m := manifest.NewManifest(h)
|
||||||
m.Features = smartcontract.HasStorage
|
m.Features = smartcontract.HasStorage
|
||||||
|
|
|
@ -314,7 +314,7 @@ func (p *PublicKey) GetVerificationScript() []byte {
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
}
|
}
|
||||||
emit.Bytes(buf.BinWriter, b)
|
emit.Bytes(buf.BinWriter, b)
|
||||||
emit.Opcode(buf.BinWriter, opcode.PUSHNULL)
|
emit.Opcodes(buf.BinWriter, opcode.PUSHNULL)
|
||||||
emit.Syscall(buf.BinWriter, interopnames.NeoCryptoVerifyWithECDsaSecp256r1)
|
emit.Syscall(buf.BinWriter, interopnames.NeoCryptoVerifyWithECDsaSecp256r1)
|
||||||
|
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
|
|
|
@ -132,7 +132,7 @@ func (c *Client) CreateNEP5MultiTransferTx(acc *wallet.Account, gas int64, recip
|
||||||
for i := range recipients {
|
for i := range recipients {
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, recipients[i].Token, "transfer", from,
|
emit.AppCallWithOperationAndArgs(w.BinWriter, recipients[i].Token, "transfer", from,
|
||||||
recipients[i].Address, recipients[i].Amount)
|
recipients[i].Address, recipients[i].Amount)
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||||
}
|
}
|
||||||
return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, transaction.Signer{
|
return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, transaction.Signer{
|
||||||
Account: acc.Contract.ScriptHash(),
|
Account: acc.Contract.ScriptHash(),
|
||||||
|
|
|
@ -107,7 +107,7 @@ func expandArrayIntoScript(script *io.BinWriter, slice []Param) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emit.Int(script, int64(len(val)))
|
emit.Int(script, int64(len(val)))
|
||||||
emit.Opcode(script, opcode.PACK)
|
emit.Opcodes(script, opcode.PACK)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("parameter type %v is not supported", fp.Type)
|
return fmt.Errorf("parameter type %v is not supported", fp.Type)
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byt
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
emit.Int(script.BinWriter, int64(len(slice)))
|
emit.Int(script.BinWriter, int64(len(slice)))
|
||||||
emit.Opcode(script.BinWriter, opcode.PACK)
|
emit.Opcodes(script.BinWriter, opcode.PACK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, erro
|
||||||
emit.Bytes(buf.BinWriter, pubKey.Bytes())
|
emit.Bytes(buf.BinWriter, pubKey.Bytes())
|
||||||
}
|
}
|
||||||
emit.Int(buf.BinWriter, int64(len(publicKeys)))
|
emit.Int(buf.BinWriter, int64(len(publicKeys)))
|
||||||
emit.Opcode(buf.BinWriter, opcode.PUSHNULL)
|
emit.Opcodes(buf.BinWriter, opcode.PUSHNULL)
|
||||||
emit.Syscall(buf.BinWriter, interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1)
|
emit.Syscall(buf.BinWriter, interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1)
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
|
|
|
@ -21,18 +21,20 @@ func Instruction(w *io.BinWriter, op opcode.Opcode, b []byte) {
|
||||||
w.WriteBytes(b)
|
w.WriteBytes(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode emits a single VM Instruction without arguments to the given buffer.
|
// Opcodes emits a single VM Instruction without arguments to the given buffer.
|
||||||
func Opcode(w *io.BinWriter, op opcode.Opcode) {
|
func Opcodes(w *io.BinWriter, ops ...opcode.Opcode) {
|
||||||
w.WriteB(byte(op))
|
for _, op := range ops {
|
||||||
|
w.WriteB(byte(op))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool emits a bool type the given buffer.
|
// Bool emits a bool type the given buffer.
|
||||||
func Bool(w *io.BinWriter, ok bool) {
|
func Bool(w *io.BinWriter, ok bool) {
|
||||||
if ok {
|
if ok {
|
||||||
Opcode(w, opcode.PUSHT)
|
Opcodes(w, opcode.PUSHT)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Opcode(w, opcode.PUSHF)
|
Opcodes(w, opcode.PUSHF)
|
||||||
Instruction(w, opcode.CONVERT, []byte{byte(stackitem.BooleanT)})
|
Instruction(w, opcode.CONVERT, []byte{byte(stackitem.BooleanT)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,15 +53,15 @@ func padRight(s int, buf []byte) []byte {
|
||||||
func Int(w *io.BinWriter, i int64) {
|
func Int(w *io.BinWriter, i int64) {
|
||||||
switch {
|
switch {
|
||||||
case i == -1:
|
case i == -1:
|
||||||
Opcode(w, opcode.PUSHM1)
|
Opcodes(w, opcode.PUSHM1)
|
||||||
case i >= 0 && i < 16:
|
case i >= 0 && i < 16:
|
||||||
val := opcode.Opcode(int(opcode.PUSH1) - 1 + int(i))
|
val := opcode.Opcode(int(opcode.PUSH1) - 1 + int(i))
|
||||||
Opcode(w, val)
|
Opcodes(w, val)
|
||||||
default:
|
default:
|
||||||
buf := bigint.ToPreallocatedBytes(big.NewInt(i), make([]byte, 0, 32))
|
buf := bigint.ToPreallocatedBytes(big.NewInt(i), make([]byte, 0, 32))
|
||||||
// l != 0 becase of switch
|
// l != 0 becase of switch
|
||||||
padSize := byte(8 - bits.LeadingZeros8(byte(len(buf)-1)))
|
padSize := byte(8 - bits.LeadingZeros8(byte(len(buf)-1)))
|
||||||
Opcode(w, opcode.PUSHINT8+opcode.Opcode(padSize))
|
Opcodes(w, opcode.PUSHINT8+opcode.Opcode(padSize))
|
||||||
w.WriteBytes(padRight(1<<padSize, buf))
|
w.WriteBytes(padRight(1<<padSize, buf))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,11 +85,11 @@ func Array(w *io.BinWriter, es ...interface{}) {
|
||||||
w.Err = errors.New("unsupported type")
|
w.Err = errors.New("unsupported type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Opcode(w, opcode.PUSHNULL)
|
Opcodes(w, opcode.PUSHNULL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Int(w, int64(len(es)))
|
Int(w, int64(len(es)))
|
||||||
Opcode(w, opcode.PACK)
|
Opcodes(w, opcode.PACK)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String emits a string to the given buffer.
|
// String emits a string to the given buffer.
|
||||||
|
|
|
@ -181,6 +181,13 @@ func TestEmitBool(t *testing.T) {
|
||||||
assert.Equal(t, opcode.Opcode(result[1]), opcode.PUSH0)
|
assert.Equal(t, opcode.Opcode(result[1]), opcode.PUSH0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEmitOpcode(t *testing.T) {
|
||||||
|
w := io.NewBufBinWriter()
|
||||||
|
Opcodes(w.BinWriter, opcode.PUSH1, opcode.NEWMAP)
|
||||||
|
result := w.Bytes()
|
||||||
|
assert.Equal(t, result, []byte{byte(opcode.PUSH1), byte(opcode.NEWMAP)})
|
||||||
|
}
|
||||||
|
|
||||||
func TestEmitString(t *testing.T) {
|
func TestEmitString(t *testing.T) {
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
str := "City Of Zion"
|
str := "City Of Zion"
|
||||||
|
|
|
@ -39,7 +39,7 @@ func TestInteropHook(t *testing.T) {
|
||||||
|
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
emit.Syscall(buf.BinWriter, "foo")
|
emit.Syscall(buf.BinWriter, "foo")
|
||||||
emit.Opcode(buf.BinWriter, opcode.RET)
|
emit.Opcodes(buf.BinWriter, opcode.RET)
|
||||||
v.Load(buf.Bytes())
|
v.Load(buf.Bytes())
|
||||||
runVM(t, v)
|
runVM(t, v)
|
||||||
assert.Equal(t, 1, v.estack.Len())
|
assert.Equal(t, 1, v.estack.Len())
|
||||||
|
@ -773,11 +773,11 @@ func TestSerializeMapCompat(t *testing.T) {
|
||||||
|
|
||||||
// Create a map, push key and value, add KV to map, serialize.
|
// Create a map, push key and value, add KV to map, serialize.
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
emit.Opcode(buf.BinWriter, opcode.NEWMAP)
|
emit.Opcodes(buf.BinWriter, opcode.NEWMAP)
|
||||||
emit.Opcode(buf.BinWriter, opcode.DUP)
|
emit.Opcodes(buf.BinWriter, opcode.DUP)
|
||||||
emit.Bytes(buf.BinWriter, []byte("key"))
|
emit.Bytes(buf.BinWriter, []byte("key"))
|
||||||
emit.Bytes(buf.BinWriter, []byte("value"))
|
emit.Bytes(buf.BinWriter, []byte("value"))
|
||||||
emit.Opcode(buf.BinWriter, opcode.SETITEM)
|
emit.Opcodes(buf.BinWriter, opcode.SETITEM)
|
||||||
emit.Syscall(buf.BinWriter, interopnames.SystemBinarySerialize)
|
emit.Syscall(buf.BinWriter, interopnames.SystemBinarySerialize)
|
||||||
require.NoError(t, buf.Err)
|
require.NoError(t, buf.Err)
|
||||||
|
|
||||||
|
@ -1654,12 +1654,12 @@ func TestSIGN(t *testing.T) {
|
||||||
func TestSimpleCall(t *testing.T) {
|
func TestSimpleCall(t *testing.T) {
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
w := buf.BinWriter
|
w := buf.BinWriter
|
||||||
emit.Opcode(w, opcode.PUSH2)
|
emit.Opcodes(w, opcode.PUSH2)
|
||||||
emit.Instruction(w, opcode.CALL, []byte{03})
|
emit.Instruction(w, opcode.CALL, []byte{03})
|
||||||
emit.Opcode(w, opcode.RET)
|
emit.Opcodes(w, opcode.RET)
|
||||||
emit.Opcode(w, opcode.PUSH10)
|
emit.Opcodes(w, opcode.PUSH10)
|
||||||
emit.Opcode(w, opcode.ADD)
|
emit.Opcodes(w, opcode.ADD)
|
||||||
emit.Opcode(w, opcode.RET)
|
emit.Opcodes(w, opcode.RET)
|
||||||
|
|
||||||
result := 12
|
result := 12
|
||||||
vm := load(buf.Bytes())
|
vm := load(buf.Bytes())
|
||||||
|
|
Loading…
Reference in a new issue