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:
Roman Khimov 2022-10-25 13:08:33 +03:00
parent 4313b7f0c7
commit 5d43367082
7 changed files with 42 additions and 47 deletions

View file

@ -99,7 +99,7 @@ func TestNEP17Balance(t *testing.T) {
}
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)
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr4))
e.CheckEOF(t)

View file

@ -61,11 +61,10 @@
"isDefault": false
},
{
"address": "NQ3nAdFQXzemHC9uvr4af2Ysap6aZJpqgN",
"address": "NfWu6j9KPLQMsWLfHz9iZRy5sNw2bUZWQL",
"key": "6PYSATFztBa3CHjSR6sLAKungUEAbQUCVE16KzmaQQ38gLeYGZ9Knd5mGv",
"label": "verify",
"contract": {
"script": "EdsgQFcAA0BXAQR4eXp7VBTAcAwOT25ORVAxMVBheW1lbnRoUEGVAW9hIUA=",
"parameters": [],
"deployed": true
},

View file

@ -914,7 +914,7 @@ func TestRunWithHistoricState(t *testing.T) {
e.checkNextLine(t, "READY: loaded 36 instructions")
e.checkStack(t, []byte{1})
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) {
@ -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.checkEvents(t, true, expectedEvent) // automatically printed after `run` command
e.checkEvents(t, false, expectedEvent) // printed after `events` command

View file

@ -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) {
verAcc, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
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) {
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.String(invocWriter.BinWriter, "")
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.
})
})
}

View file

@ -347,7 +347,7 @@ func TestEncodeDefaultValue(t *testing.T) {
for p, l := range map[ParamType]int{
UnknownType: 0,
AnyType: 66,
BoolType: 3,
BoolType: 2,
IntegerType: 33,
ByteArrayType: 66,
StringType: 66,

View file

@ -31,12 +31,11 @@ func Opcodes(w *io.BinWriter, ops ...opcode.Opcode) {
// Bool emits a bool type to the given buffer.
func Bool(w *io.BinWriter, ok bool) {
if ok {
Opcodes(w, opcode.PUSHT)
} else {
Opcodes(w, opcode.PUSHF)
var opVal = opcode.PUSHF
if !ok {
opVal = opcode.PUSHT
}
Instruction(w, opcode.CONVERT, []byte{byte(stackitem.BooleanT)})
Opcodes(w, opVal, opcode.NOT)
}
func padRight(s int, buf []byte) []byte {

View file

@ -231,35 +231,34 @@ func TestEmitArray(t *testing.T) {
assert.EqualValues(t, opcode.PUSHDATA1, res[0])
assert.EqualValues(t, 2, res[1])
assert.EqualValues(t, []byte{0xCA, 0xFE}, res[2:4])
assert.EqualValues(t, opcode.PUSHT, res[4])
assert.EqualValues(t, opcode.CONVERT, res[5])
assert.EqualValues(t, stackitem.BooleanT, res[6])
assert.EqualValues(t, opcode.PUSHDATA1, res[7])
assert.EqualValues(t, 3, res[8])
assert.EqualValues(t, []byte("str"), res[9:12])
assert.EqualValues(t, opcode.PUSH1, res[12])
assert.EqualValues(t, opcode.PUSHNULL, res[13])
assert.EqualValues(t, opcode.PUSH2, res[14])
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])
assert.EqualValues(t, opcode.PUSHDATA1, res[36])
assert.EqualValues(t, 32, res[37])
assert.EqualValues(t, u256.BytesBE(), res[38:70])
assert.EqualValues(t, opcode.PUSHDATA1, res[70])
assert.EqualValues(t, 20, res[71])
assert.EqualValues(t, u160.BytesBE(), res[72:92])
assert.EqualValues(t, opcode.PUSHDATA1, res[92])
assert.EqualValues(t, 32, res[93])
assert.EqualValues(t, u256.BytesBE(), res[94:126])
assert.EqualValues(t, opcode.PUSHDATA1, res[126])
assert.EqualValues(t, 20, res[127])
assert.EqualValues(t, u160.BytesBE(), res[128:148])
assert.EqualValues(t, opcode.PUSHF, res[4])
assert.EqualValues(t, opcode.NOT, res[5])
assert.EqualValues(t, opcode.PUSHDATA1, res[6])
assert.EqualValues(t, 3, res[7])
assert.EqualValues(t, []byte("str"), res[8:11])
assert.EqualValues(t, opcode.PUSH1, res[11])
assert.EqualValues(t, opcode.PUSHNULL, res[12])
assert.EqualValues(t, opcode.PUSH2, res[13])
assert.EqualValues(t, opcode.PUSH1, res[14])
assert.EqualValues(t, opcode.PUSH2, res[15])
assert.EqualValues(t, opcode.PACK, res[16])
assert.EqualValues(t, opcode.PUSHINT128, res[17])
assert.EqualValues(t, veryBig, bigint.FromBytes(res[18:34]))
assert.EqualValues(t, opcode.PUSH0, res[34])
assert.EqualValues(t, opcode.PUSHDATA1, res[35])
assert.EqualValues(t, 32, res[36])
assert.EqualValues(t, u256.BytesBE(), res[37:69])
assert.EqualValues(t, opcode.PUSHDATA1, res[69])
assert.EqualValues(t, 20, res[70])
assert.EqualValues(t, u160.BytesBE(), res[71:91])
assert.EqualValues(t, opcode.PUSHDATA1, res[91])
assert.EqualValues(t, 32, res[92])
assert.EqualValues(t, u256.BytesBE(), res[93:125])
assert.EqualValues(t, opcode.PUSHDATA1, res[125])
assert.EqualValues(t, 20, res[126])
assert.EqualValues(t, u160.BytesBE(), res[127:147])
assert.EqualValues(t, opcode.PUSHNULL, res[147])
assert.EqualValues(t, opcode.PUSHNULL, res[148])
assert.EqualValues(t, opcode.PUSHNULL, res[149])
})
t.Run("empty", func(t *testing.T) {
@ -281,12 +280,10 @@ func TestEmitBool(t *testing.T) {
Bool(buf.BinWriter, true)
Bool(buf.BinWriter, false)
result := buf.Bytes()
assert.EqualValues(t, opcode.PUSH1, result[0])
assert.EqualValues(t, opcode.CONVERT, result[1])
assert.EqualValues(t, stackitem.BooleanT, result[2])
assert.EqualValues(t, opcode.PUSH0, result[3])
assert.EqualValues(t, opcode.CONVERT, result[4])
assert.EqualValues(t, stackitem.BooleanT, result[5])
assert.EqualValues(t, opcode.PUSH0, result[0])
assert.EqualValues(t, opcode.NOT, result[1])
assert.EqualValues(t, opcode.PUSH1, result[2])
assert.EqualValues(t, opcode.NOT, result[3])
}
func TestEmitOpcode(t *testing.T) {