Merge pull request #803 from nspcc-dev/feature/appcall
emit: implement AppCallWithOperationAndArgs
This commit is contained in:
commit
c738975b7b
4 changed files with 64 additions and 24 deletions
|
@ -317,12 +317,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
|
|
||||||
// Now invoke this contract.
|
// Now invoke this contract.
|
||||||
script = io.NewBufBinWriter()
|
script = io.NewBufBinWriter()
|
||||||
emit.String(script.BinWriter, "testvalue")
|
emit.AppCallWithOperationAndArgs(script.BinWriter, hash.Hash160(avm), "Put", "testkey", "testvalue")
|
||||||
emit.String(script.BinWriter, "testkey")
|
|
||||||
emit.Int(script.BinWriter, 2)
|
|
||||||
emit.Opcode(script.BinWriter, opcode.PACK)
|
|
||||||
emit.String(script.BinWriter, "Put")
|
|
||||||
emit.AppCall(script.BinWriter, hash.Hash160(avm), false)
|
|
||||||
|
|
||||||
txInv := transaction.NewInvocationTX(script.Bytes(), 0)
|
txInv := transaction.NewInvocationTX(script.Bytes(), 0)
|
||||||
b = bc.newBlock(newMinerTX(), txInv)
|
b = bc.newBlock(newMinerTX(), txInv)
|
||||||
|
@ -354,10 +349,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
|
|
||||||
sh := hash.Hash160(avm)
|
sh := hash.Hash160(avm)
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.Int(w.BinWriter, 0)
|
emit.AppCallWithOperationAndArgs(w.BinWriter, sh, "init")
|
||||||
emit.Opcode(w.BinWriter, opcode.NEWARRAY)
|
|
||||||
emit.String(w.BinWriter, "init")
|
|
||||||
emit.AppCall(w.BinWriter, sh, true)
|
|
||||||
initTx := transaction.NewInvocationTX(w.Bytes(), 0)
|
initTx := transaction.NewInvocationTX(w.Bytes(), 0)
|
||||||
transferTx := newNEP5Transfer(sh, sh, priv0.GetScriptHash(), 1000)
|
transferTx := newNEP5Transfer(sh, sh, priv0.GetScriptHash(), 1000)
|
||||||
|
|
||||||
|
@ -403,13 +395,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.Int(w.BinWriter, amount)
|
emit.AppCallWithOperationAndArgs(w.BinWriter, sc, "transfer", from, to, amount)
|
||||||
emit.Bytes(w.BinWriter, to.BytesBE())
|
|
||||||
emit.Bytes(w.BinWriter, from.BytesBE())
|
|
||||||
emit.Int(w.BinWriter, 3)
|
|
||||||
emit.Opcode(w.BinWriter, opcode.PACK)
|
|
||||||
emit.String(w.BinWriter, "transfer")
|
|
||||||
emit.AppCall(w.BinWriter, sc, false)
|
|
||||||
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
||||||
|
|
||||||
script := w.Bytes()
|
script := w.Bytes()
|
||||||
|
|
|
@ -104,13 +104,7 @@ func (c *Client) TransferNEP5(acc *wallet.Account, to util.Uint160, token *walle
|
||||||
// Note: we don't use invoke function here because it requires
|
// Note: we don't use invoke function here because it requires
|
||||||
// 2 round trips instead of one.
|
// 2 round trips instead of one.
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.Int(w.BinWriter, amount)
|
emit.AppCallWithOperationAndArgs(w.BinWriter, token.Hash, "transfer", from, to, amount)
|
||||||
emit.Bytes(w.BinWriter, to.BytesBE())
|
|
||||||
emit.Bytes(w.BinWriter, from.BytesBE())
|
|
||||||
emit.Int(w.BinWriter, 3)
|
|
||||||
emit.Opcode(w.BinWriter, opcode.PACK)
|
|
||||||
emit.String(w.BinWriter, "transfer")
|
|
||||||
emit.AppCall(w.BinWriter, token.Hash, false)
|
|
||||||
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
||||||
|
|
||||||
tx := transaction.NewInvocationTX(w.Bytes(), gas)
|
tx := transaction.NewInvocationTX(w.Bytes(), gas)
|
||||||
|
|
|
@ -48,6 +48,29 @@ func Int(w *io.BinWriter, i int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Array emits array of elements to the given buffer.
|
||||||
|
func Array(w *io.BinWriter, es ...interface{}) {
|
||||||
|
for i := len(es) - 1; i >= 0; i-- {
|
||||||
|
switch e := es[i].(type) {
|
||||||
|
case int64:
|
||||||
|
Int(w, e)
|
||||||
|
case string:
|
||||||
|
String(w, e)
|
||||||
|
case util.Uint160:
|
||||||
|
Bytes(w, e.BytesBE())
|
||||||
|
case []byte:
|
||||||
|
Bytes(w, e)
|
||||||
|
case bool:
|
||||||
|
Bool(w, e)
|
||||||
|
default:
|
||||||
|
w.Err = errors.New("unsupported type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Int(w, int64(len(es)))
|
||||||
|
Opcode(w, opcode.PACK)
|
||||||
|
}
|
||||||
|
|
||||||
// String emits a string to the given buffer.
|
// String emits a string to the given buffer.
|
||||||
func String(w *io.BinWriter, s string) {
|
func String(w *io.BinWriter, s string) {
|
||||||
Bytes(w, []byte(s))
|
Bytes(w, []byte(s))
|
||||||
|
@ -118,6 +141,13 @@ func AppCall(w *io.BinWriter, scriptHash util.Uint160, tailCall bool) {
|
||||||
Instruction(w, op, scriptHash.BytesBE())
|
Instruction(w, op, scriptHash.BytesBE())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppCallWithOperationAndArgs emits an APPCALL with the given operation and arguments.
|
||||||
|
func AppCallWithOperationAndArgs(w *io.BinWriter, scriptHash util.Uint160, operation string, args ...interface{}) {
|
||||||
|
Array(w, args...)
|
||||||
|
String(w, operation)
|
||||||
|
AppCall(w, scriptHash, false)
|
||||||
|
}
|
||||||
|
|
||||||
// AppCallWithOperationAndData emits an appcall with the given operation and data.
|
// AppCallWithOperationAndData emits an appcall with the given operation and data.
|
||||||
func AppCallWithOperationAndData(w *io.BinWriter, scriptHash util.Uint160, operation string, data []byte) {
|
func AppCallWithOperationAndData(w *io.BinWriter, scriptHash util.Uint160, operation string, data []byte) {
|
||||||
Bytes(w, data)
|
Bytes(w, data)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEmitInt(t *testing.T) {
|
func TestEmitInt(t *testing.T) {
|
||||||
|
@ -107,6 +108,35 @@ func TestBytes(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEmitArray(t *testing.T) {
|
||||||
|
t.Run("good", func(t *testing.T) {
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
Array(buf.BinWriter, int64(1), "str", true, []byte{0xCA, 0xFE})
|
||||||
|
require.NoError(t, buf.Err)
|
||||||
|
|
||||||
|
res := buf.Bytes()
|
||||||
|
assert.EqualValues(t, opcode.PUSHBYTES2, res[0])
|
||||||
|
assert.EqualValues(t, []byte{0xCA, 0xFE}, res[1:3])
|
||||||
|
assert.EqualValues(t, opcode.PUSHT, res[3])
|
||||||
|
assert.EqualValues(t, opcode.PUSHBYTES3, res[4])
|
||||||
|
assert.EqualValues(t, []byte("str"), res[5:8])
|
||||||
|
assert.EqualValues(t, opcode.PUSH1, res[8])
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty", func(t *testing.T) {
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
Array(buf.BinWriter)
|
||||||
|
require.NoError(t, buf.Err)
|
||||||
|
assert.EqualValues(t, []byte{0, byte(opcode.PACK)}, buf.Bytes())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid type", func(t *testing.T) {
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
Array(buf.BinWriter, struct{}{})
|
||||||
|
require.Error(t, buf.Err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestEmitBool(t *testing.T) {
|
func TestEmitBool(t *testing.T) {
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
Bool(buf.BinWriter, true)
|
Bool(buf.BinWriter, true)
|
||||||
|
|
Loading…
Reference in a new issue