emit: allow to emit big.Int

This commit is contained in:
Evgeniy Stratonikov 2021-03-05 14:16:34 +03:00
parent d9e62de454
commit b780a64b4d
2 changed files with 23 additions and 6 deletions

View file

@ -59,14 +59,21 @@ func Int(w *io.BinWriter, i int64) {
val := opcode.Opcode(int(opcode.PUSH1) - 1 + int(i))
Opcodes(w, val)
default:
buf := bigint.ToPreallocatedBytes(big.NewInt(i), make([]byte, 0, 32))
// l != 0 becase of switch
padSize := byte(8 - bits.LeadingZeros8(byte(len(buf)-1)))
Opcodes(w, opcode.PUSHINT8+opcode.Opcode(padSize))
w.WriteBytes(padRight(1<<padSize, buf))
bigInt(w, big.NewInt(i))
}
}
func bigInt(w *io.BinWriter, n *big.Int) {
buf := bigint.ToPreallocatedBytes(n, make([]byte, 0, 32))
if len(buf) == 0 {
Opcodes(w, opcode.PUSH0)
return
}
padSize := byte(8 - bits.LeadingZeros8(byte(len(buf)-1)))
Opcodes(w, opcode.PUSHINT8+opcode.Opcode(padSize))
w.WriteBytes(padRight(1<<padSize, buf))
}
// Array emits array of elements to the given buffer.
func Array(w *io.BinWriter, es ...interface{}) {
for i := len(es) - 1; i >= 0; i-- {
@ -75,6 +82,8 @@ func Array(w *io.BinWriter, es ...interface{}) {
Array(w, e...)
case int64:
Int(w, e)
case *big.Int:
bigInt(w, e)
case string:
String(w, e)
case util.Uint160:

View file

@ -3,6 +3,8 @@ package emit
import (
"encoding/binary"
"errors"
"math"
"math/big"
"testing"
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
@ -144,7 +146,10 @@ func TestBytes(t *testing.T) {
func TestEmitArray(t *testing.T) {
t.Run("good", func(t *testing.T) {
buf := io.NewBufBinWriter()
Array(buf.BinWriter, []interface{}{int64(1), int64(2)}, nil, int64(1), "str", true, []byte{0xCA, 0xFE})
veryBig := new(big.Int).SetUint64(math.MaxUint64)
veryBig.Add(veryBig, big.NewInt(1))
Array(buf.BinWriter, big.NewInt(0), veryBig,
[]interface{}{int64(1), int64(2)}, nil, int64(1), "str", true, []byte{0xCA, 0xFE})
require.NoError(t, buf.Err)
res := buf.Bytes()
@ -163,6 +168,9 @@ func TestEmitArray(t *testing.T) {
assert.EqualValues(t, opcode.PUSH1, res[15])
assert.EqualValues(t, opcode.PUSH2, res[16])
assert.EqualValues(t, opcode.PACK, res[17])
assert.EqualValues(t, opcode.PUSHINT128, res[18])
assert.EqualValues(t, veryBig, bigint.FromBytes(res[19:35]))
assert.EqualValues(t, opcode.PUSH0, res[35])
})
t.Run("empty", func(t *testing.T) {