emit: optimize Bool GAS cost
NOT is 1 byte shorter and 2048 times cheaper than CONVERT. Inspired by neo-project/neo-vm#493.
This commit is contained in:
parent
4313b7f0c7
commit
5d43367082
7 changed files with 42 additions and 47 deletions
|
@ -99,7 +99,7 @@ func TestNEP17Balance(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
e.CheckNextLine(t, "^\\s*$")
|
e.CheckNextLine(t, "^\\s*$")
|
||||||
addr4, err := address.StringToUint160("NQ3nAdFQXzemHC9uvr4af2Ysap6aZJpqgN") // deployed verify.go contract
|
addr4, err := address.StringToUint160("NfWu6j9KPLQMsWLfHz9iZRy5sNw2bUZWQL") // deployed verify.go contract
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr4))
|
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr4))
|
||||||
e.CheckEOF(t)
|
e.CheckEOF(t)
|
||||||
|
|
3
cli/testdata/wallet1_solo.json
vendored
3
cli/testdata/wallet1_solo.json
vendored
|
@ -61,11 +61,10 @@
|
||||||
"isDefault": false
|
"isDefault": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "NQ3nAdFQXzemHC9uvr4af2Ysap6aZJpqgN",
|
"address": "NfWu6j9KPLQMsWLfHz9iZRy5sNw2bUZWQL",
|
||||||
"key": "6PYSATFztBa3CHjSR6sLAKungUEAbQUCVE16KzmaQQ38gLeYGZ9Knd5mGv",
|
"key": "6PYSATFztBa3CHjSR6sLAKungUEAbQUCVE16KzmaQQ38gLeYGZ9Knd5mGv",
|
||||||
"label": "verify",
|
"label": "verify",
|
||||||
"contract": {
|
"contract": {
|
||||||
"script": "EdsgQFcAA0BXAQR4eXp7VBTAcAwOT25ORVAxMVBheW1lbnRoUEGVAW9hIUA=",
|
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"deployed": true
|
"deployed": true
|
||||||
},
|
},
|
||||||
|
|
|
@ -914,7 +914,7 @@ func TestRunWithHistoricState(t *testing.T) {
|
||||||
e.checkNextLine(t, "READY: loaded 36 instructions")
|
e.checkNextLine(t, "READY: loaded 36 instructions")
|
||||||
e.checkStack(t, []byte{1})
|
e.checkStack(t, []byte{1})
|
||||||
e.checkNextLine(t, "READY: loaded 36 instructions")
|
e.checkNextLine(t, "READY: loaded 36 instructions")
|
||||||
e.checkNextLineExact(t, "Error: at instruction 31 (SYSCALL): failed to invoke syscall 1381727586: called contract a00e3c2643a08a452d8b0bdd31849ae11a17c445 not found: key not found\n")
|
e.checkNextLineExact(t, "Error: at instruction 31 (SYSCALL): failed to invoke syscall 1381727586: called contract cd583ac7a1a4faef70d6e9f513bc988dde22f672 not found: key not found\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEvents(t *testing.T) {
|
func TestEvents(t *testing.T) {
|
||||||
|
@ -939,7 +939,7 @@ func TestEvents(t *testing.T) {
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
e.checkNextLine(t, "READY: loaded 44 instructions")
|
e.checkNextLine(t, "READY: loaded 43 instructions")
|
||||||
e.checkStack(t, stackitem.Null{})
|
e.checkStack(t, stackitem.Null{})
|
||||||
e.checkEvents(t, true, expectedEvent) // automatically printed after `run` command
|
e.checkEvents(t, true, expectedEvent) // automatically printed after `run` command
|
||||||
e.checkEvents(t, false, expectedEvent) // printed after `events` command
|
e.checkEvents(t, false, expectedEvent) // printed after `events` command
|
||||||
|
|
|
@ -2557,7 +2557,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
||||||
t.Run("contract-based verification with parameters", func(t *testing.T) {
|
t.Run("contract-based verification with parameters", func(t *testing.T) {
|
||||||
verAcc, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
verAcc, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
checkContract(t, verAcc, []byte{}, 737530) // No C# match, but we believe it's OK and it differs from the one above.
|
checkContract(t, verAcc, []byte{}, 490890) // No C# match, but we believe it's OK and it differs from the one above.
|
||||||
})
|
})
|
||||||
t.Run("contract-based verification with invocation script", func(t *testing.T) {
|
t.Run("contract-based verification with invocation script", func(t *testing.T) {
|
||||||
verAcc, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
verAcc, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
||||||
|
@ -2567,7 +2567,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
||||||
emit.Int(invocWriter.BinWriter, 5)
|
emit.Int(invocWriter.BinWriter, 5)
|
||||||
emit.String(invocWriter.BinWriter, "")
|
emit.String(invocWriter.BinWriter, "")
|
||||||
invocScript := invocWriter.Bytes()
|
invocScript := invocWriter.Bytes()
|
||||||
checkContract(t, verAcc, invocScript, 640360) // No C# match, but we believe it's OK and it has a specific invocation script overriding anything server-side.
|
checkContract(t, verAcc, invocScript, 393720) // No C# match, but we believe it's OK and it has a specific invocation script overriding anything server-side.
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,7 +347,7 @@ func TestEncodeDefaultValue(t *testing.T) {
|
||||||
for p, l := range map[ParamType]int{
|
for p, l := range map[ParamType]int{
|
||||||
UnknownType: 0,
|
UnknownType: 0,
|
||||||
AnyType: 66,
|
AnyType: 66,
|
||||||
BoolType: 3,
|
BoolType: 2,
|
||||||
IntegerType: 33,
|
IntegerType: 33,
|
||||||
ByteArrayType: 66,
|
ByteArrayType: 66,
|
||||||
StringType: 66,
|
StringType: 66,
|
||||||
|
|
|
@ -31,12 +31,11 @@ func Opcodes(w *io.BinWriter, ops ...opcode.Opcode) {
|
||||||
|
|
||||||
// Bool emits a bool type to the given buffer.
|
// Bool emits a bool type to the given buffer.
|
||||||
func Bool(w *io.BinWriter, ok bool) {
|
func Bool(w *io.BinWriter, ok bool) {
|
||||||
if ok {
|
var opVal = opcode.PUSHF
|
||||||
Opcodes(w, opcode.PUSHT)
|
if !ok {
|
||||||
} else {
|
opVal = opcode.PUSHT
|
||||||
Opcodes(w, opcode.PUSHF)
|
|
||||||
}
|
}
|
||||||
Instruction(w, opcode.CONVERT, []byte{byte(stackitem.BooleanT)})
|
Opcodes(w, opVal, opcode.NOT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func padRight(s int, buf []byte) []byte {
|
func padRight(s int, buf []byte) []byte {
|
||||||
|
|
|
@ -231,35 +231,34 @@ func TestEmitArray(t *testing.T) {
|
||||||
assert.EqualValues(t, opcode.PUSHDATA1, res[0])
|
assert.EqualValues(t, opcode.PUSHDATA1, res[0])
|
||||||
assert.EqualValues(t, 2, res[1])
|
assert.EqualValues(t, 2, res[1])
|
||||||
assert.EqualValues(t, []byte{0xCA, 0xFE}, res[2:4])
|
assert.EqualValues(t, []byte{0xCA, 0xFE}, res[2:4])
|
||||||
assert.EqualValues(t, opcode.PUSHT, res[4])
|
assert.EqualValues(t, opcode.PUSHF, res[4])
|
||||||
assert.EqualValues(t, opcode.CONVERT, res[5])
|
assert.EqualValues(t, opcode.NOT, res[5])
|
||||||
assert.EqualValues(t, stackitem.BooleanT, res[6])
|
assert.EqualValues(t, opcode.PUSHDATA1, res[6])
|
||||||
assert.EqualValues(t, opcode.PUSHDATA1, res[7])
|
assert.EqualValues(t, 3, res[7])
|
||||||
assert.EqualValues(t, 3, res[8])
|
assert.EqualValues(t, []byte("str"), res[8:11])
|
||||||
assert.EqualValues(t, []byte("str"), res[9:12])
|
assert.EqualValues(t, opcode.PUSH1, res[11])
|
||||||
assert.EqualValues(t, opcode.PUSH1, res[12])
|
assert.EqualValues(t, opcode.PUSHNULL, res[12])
|
||||||
assert.EqualValues(t, opcode.PUSHNULL, res[13])
|
assert.EqualValues(t, opcode.PUSH2, res[13])
|
||||||
assert.EqualValues(t, opcode.PUSH2, res[14])
|
assert.EqualValues(t, opcode.PUSH1, res[14])
|
||||||
assert.EqualValues(t, opcode.PUSH1, res[15])
|
assert.EqualValues(t, opcode.PUSH2, res[15])
|
||||||
assert.EqualValues(t, opcode.PUSH2, res[16])
|
assert.EqualValues(t, opcode.PACK, res[16])
|
||||||
assert.EqualValues(t, opcode.PACK, res[17])
|
assert.EqualValues(t, opcode.PUSHINT128, res[17])
|
||||||
assert.EqualValues(t, opcode.PUSHINT128, res[18])
|
assert.EqualValues(t, veryBig, bigint.FromBytes(res[18:34]))
|
||||||
assert.EqualValues(t, veryBig, bigint.FromBytes(res[19:35]))
|
assert.EqualValues(t, opcode.PUSH0, res[34])
|
||||||
assert.EqualValues(t, opcode.PUSH0, res[35])
|
assert.EqualValues(t, opcode.PUSHDATA1, res[35])
|
||||||
assert.EqualValues(t, opcode.PUSHDATA1, res[36])
|
assert.EqualValues(t, 32, res[36])
|
||||||
assert.EqualValues(t, 32, res[37])
|
assert.EqualValues(t, u256.BytesBE(), res[37:69])
|
||||||
assert.EqualValues(t, u256.BytesBE(), res[38:70])
|
assert.EqualValues(t, opcode.PUSHDATA1, res[69])
|
||||||
assert.EqualValues(t, opcode.PUSHDATA1, res[70])
|
assert.EqualValues(t, 20, res[70])
|
||||||
assert.EqualValues(t, 20, res[71])
|
assert.EqualValues(t, u160.BytesBE(), res[71:91])
|
||||||
assert.EqualValues(t, u160.BytesBE(), res[72:92])
|
assert.EqualValues(t, opcode.PUSHDATA1, res[91])
|
||||||
assert.EqualValues(t, opcode.PUSHDATA1, res[92])
|
assert.EqualValues(t, 32, res[92])
|
||||||
assert.EqualValues(t, 32, res[93])
|
assert.EqualValues(t, u256.BytesBE(), res[93:125])
|
||||||
assert.EqualValues(t, u256.BytesBE(), res[94:126])
|
assert.EqualValues(t, opcode.PUSHDATA1, res[125])
|
||||||
assert.EqualValues(t, opcode.PUSHDATA1, res[126])
|
assert.EqualValues(t, 20, res[126])
|
||||||
assert.EqualValues(t, 20, res[127])
|
assert.EqualValues(t, u160.BytesBE(), res[127:147])
|
||||||
assert.EqualValues(t, u160.BytesBE(), res[128:148])
|
assert.EqualValues(t, opcode.PUSHNULL, res[147])
|
||||||
assert.EqualValues(t, opcode.PUSHNULL, res[148])
|
assert.EqualValues(t, opcode.PUSHNULL, res[148])
|
||||||
assert.EqualValues(t, opcode.PUSHNULL, res[149])
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("empty", func(t *testing.T) {
|
t.Run("empty", func(t *testing.T) {
|
||||||
|
@ -281,12 +280,10 @@ func TestEmitBool(t *testing.T) {
|
||||||
Bool(buf.BinWriter, true)
|
Bool(buf.BinWriter, true)
|
||||||
Bool(buf.BinWriter, false)
|
Bool(buf.BinWriter, false)
|
||||||
result := buf.Bytes()
|
result := buf.Bytes()
|
||||||
assert.EqualValues(t, opcode.PUSH1, result[0])
|
assert.EqualValues(t, opcode.PUSH0, result[0])
|
||||||
assert.EqualValues(t, opcode.CONVERT, result[1])
|
assert.EqualValues(t, opcode.NOT, result[1])
|
||||||
assert.EqualValues(t, stackitem.BooleanT, result[2])
|
assert.EqualValues(t, opcode.PUSH1, result[2])
|
||||||
assert.EqualValues(t, opcode.PUSH0, result[3])
|
assert.EqualValues(t, opcode.NOT, result[3])
|
||||||
assert.EqualValues(t, opcode.CONVERT, result[4])
|
|
||||||
assert.EqualValues(t, stackitem.BooleanT, result[5])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmitOpcode(t *testing.T) {
|
func TestEmitOpcode(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue