Fixed sstore gas computation, empty sha3, smod, sdiv (#71)

* Fixed sstore gas computation, fixed empty sha3

* Fixed smod and sdiv

* Comments addressed
This commit is contained in:
Yuriy Glukhov 2018-07-18 12:14:28 +03:00 committed by Mamy Ratsimbazafy
parent ca5eba20f8
commit 6c67115ef5
4 changed files with 64 additions and 45 deletions

View File

@ -150,12 +150,12 @@ VMTests
+ mulmoddivByZero2.json OK + mulmoddivByZero2.json OK
+ mulmoddivByZero3.json OK + mulmoddivByZero3.json OK
+ not1.json OK + not1.json OK
- sdiv0.json Fail + sdiv0.json OK
+ sdiv1.json OK + sdiv1.json OK
+ sdiv2.json OK + sdiv2.json OK
- sdiv3.json Fail + sdiv3.json OK
- sdiv4.json Fail + sdiv4.json OK
- sdiv5.json Fail + sdiv5.json OK
+ sdiv6.json OK + sdiv6.json OK
+ sdiv7.json OK + sdiv7.json OK
+ sdiv8.json OK + sdiv8.json OK
@ -164,8 +164,8 @@ VMTests
+ sdivByZero1.json OK + sdivByZero1.json OK
+ sdivByZero2.json OK + sdivByZero2.json OK
+ sdiv_dejavu.json OK + sdiv_dejavu.json OK
- sdiv_i256min.json Fail + sdiv_i256min.json OK
- sdiv_i256min2.json Fail + sdiv_i256min2.json OK
+ sdiv_i256min3.json OK + sdiv_i256min3.json OK
+ signextendInvalidByteNumber.json OK + signextendInvalidByteNumber.json OK
+ signextend_00.json OK + signextend_00.json OK
@ -180,9 +180,9 @@ VMTests
+ signextend_Overflow_dj42.json OK + signextend_Overflow_dj42.json OK
+ signextend_bigBytePlus1.json OK + signextend_bigBytePlus1.json OK
+ signextend_bitIsSet.json OK + signextend_bitIsSet.json OK
- smod0.json Fail + smod0.json OK
- smod1.json Fail + smod1.json OK
- smod2.json Fail + smod2.json OK
+ smod3.json OK + smod3.json OK
+ smod4.json OK + smod4.json OK
+ smod5.json OK + smod5.json OK
@ -190,7 +190,7 @@ VMTests
+ smod7.json OK + smod7.json OK
+ smod8_byZero.json OK + smod8_byZero.json OK
+ smod_i256min1.json OK + smod_i256min1.json OK
- smod_i256min2.json Fail + smod_i256min2.json OK
+ stop.json OK + stop.json OK
+ sub0.json OK + sub0.json OK
+ sub1.json OK + sub1.json OK
@ -198,7 +198,7 @@ VMTests
+ sub3.json OK + sub3.json OK
+ sub4.json OK + sub4.json OK
``` ```
OK: 185/195 Fail: 10/195 Skip: 0/195 OK: 195/195 Fail: 0/195 Skip: 0/195
## vmBitwiseLogicOperation ## vmBitwiseLogicOperation
```diff ```diff
+ and0.json OK + and0.json OK
@ -349,7 +349,7 @@ OK: 28/52 Fail: 9/52 Skip: 15/52
+ BlockNumberDynamicJumpi0.json OK + BlockNumberDynamicJumpi0.json OK
+ BlockNumberDynamicJumpi1.json OK + BlockNumberDynamicJumpi1.json OK
+ BlockNumberDynamicJumpi1_jumpdest.json OK + BlockNumberDynamicJumpi1_jumpdest.json OK
- BlockNumberDynamicJumpiAfterStop.json Fail + BlockNumberDynamicJumpiAfterStop.json OK
- BlockNumberDynamicJumpiOutsideBoundary.json Fail - BlockNumberDynamicJumpiOutsideBoundary.json Fail
+ BlockNumberDynamicJumpifInsidePushWithJumpDest.json OK + BlockNumberDynamicJumpifInsidePushWithJumpDest.json OK
+ BlockNumberDynamicJumpifInsidePushWithoutJumpDest.json OK + BlockNumberDynamicJumpifInsidePushWithoutJumpDest.json OK
@ -361,7 +361,7 @@ OK: 28/52 Fail: 9/52 Skip: 15/52
+ DynamicJump0_jumpdest2.json OK + DynamicJump0_jumpdest2.json OK
+ DynamicJump0_withoutJumpdest.json OK + DynamicJump0_withoutJumpdest.json OK
+ DynamicJump1.json OK + DynamicJump1.json OK
- DynamicJumpAfterStop.json Fail + DynamicJumpAfterStop.json OK
+ DynamicJumpInsidePushWithJumpDest.json OK + DynamicJumpInsidePushWithJumpDest.json OK
+ DynamicJumpInsidePushWithoutJumpDest.json OK + DynamicJumpInsidePushWithoutJumpDest.json OK
+ DynamicJumpJD_DependsOnJumps0.json OK + DynamicJumpJD_DependsOnJumps0.json OK
@ -378,7 +378,7 @@ OK: 28/52 Fail: 9/52 Skip: 15/52
+ DynamicJumpi0.json OK + DynamicJumpi0.json OK
+ DynamicJumpi1.json OK + DynamicJumpi1.json OK
+ DynamicJumpi1_jumpdest.json OK + DynamicJumpi1_jumpdest.json OK
- DynamicJumpiAfterStop.json Fail + DynamicJumpiAfterStop.json OK
- DynamicJumpiOutsideBoundary.json Fail - DynamicJumpiOutsideBoundary.json Fail
+ DynamicJumpifInsidePushWithJumpDest.json OK + DynamicJumpifInsidePushWithJumpDest.json OK
+ DynamicJumpifInsidePushWithoutJumpDest.json OK + DynamicJumpifInsidePushWithoutJumpDest.json OK
@ -423,13 +423,13 @@ OK: 28/52 Fail: 9/52 Skip: 15/52
+ jump0_outOfBoundary.json OK + jump0_outOfBoundary.json OK
+ jump0_withoutJumpdest.json OK + jump0_withoutJumpdest.json OK
+ jump1.json OK + jump1.json OK
- jumpAfterStop.json Fail + jumpAfterStop.json OK
+ jumpDynamicJumpSameDest.json OK + jumpDynamicJumpSameDest.json OK
+ jumpHigh.json OK + jumpHigh.json OK
+ jumpInsidePushWithJumpDest.json OK + jumpInsidePushWithJumpDest.json OK
+ jumpInsidePushWithoutJumpDest.json OK + jumpInsidePushWithoutJumpDest.json OK
+ jumpOntoJump.json OK + jumpOntoJump.json OK
- jumpTo1InstructionafterJump.json Fail + jumpTo1InstructionafterJump.json OK
+ jumpTo1InstructionafterJump_jumpdestFirstInstruction.json OK + jumpTo1InstructionafterJump_jumpdestFirstInstruction.json OK
+ jumpTo1InstructionafterJump_noJumpDest.json OK + jumpTo1InstructionafterJump_noJumpDest.json OK
- jumpToUint64maxPlus1.json Fail - jumpToUint64maxPlus1.json Fail
@ -438,7 +438,7 @@ OK: 28/52 Fail: 9/52 Skip: 15/52
+ jumpi0.json OK + jumpi0.json OK
+ jumpi1.json OK + jumpi1.json OK
+ jumpi1_jumpdest.json OK + jumpi1_jumpdest.json OK
- jumpiAfterStop.json Fail + jumpiAfterStop.json OK
- jumpiOutsideBoundary.json Fail - jumpiOutsideBoundary.json Fail
- jumpiToUint64maxPlus1.json Fail - jumpiToUint64maxPlus1.json Fail
+ jumpiToUintmaxPlus1.json OK + jumpiToUintmaxPlus1.json OK
@ -476,14 +476,14 @@ OK: 28/52 Fail: 9/52 Skip: 15/52
+ sha3MemExp.json OK + sha3MemExp.json OK
+ sstore_load_0.json OK + sstore_load_0.json OK
- sstore_load_1.json Fail - sstore_load_1.json Fail
- sstore_load_2.json Fail + sstore_load_2.json OK
+ sstore_underflow.json OK + sstore_underflow.json OK
- stack_loop.json Fail - stack_loop.json Fail
+ stackjump1.json OK + stackjump1.json OK
+ swapAt52becameMstore.json OK + swapAt52becameMstore.json OK
+ when.json OK + when.json OK
``` ```
OK: 113/145 Fail: 31/145 Skip: 1/145 OK: 120/145 Fail: 24/145 Skip: 1/145
## vmLogTest ## vmLogTest
```diff ```diff
+ log0_emptyMem.json OK + log0_emptyMem.json OK

View File

@ -46,7 +46,7 @@ const
GAS_LIMIT_MINIMUM* = 5000 GAS_LIMIT_MINIMUM* = 5000
BLANK_ROOT_HASH* = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".toDigest BLANK_ROOT_HASH* = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".toDigest
EMPTY_SHA3* = "883f7328a6c30727a655daff17eba3a86049871bc7839a5b71e2bc26a99c4d4c".toDigest EMPTY_SHA3* = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".toDigest
GAS_MOD_EXP_QUADRATIC_DENOMINATOR* = 20.u256 GAS_MOD_EXP_QUADRATIC_DENOMINATOR* = 20.u256

View File

@ -44,12 +44,20 @@ op divide, inline = true, lhs, rhs:
op sdiv, inline = true, lhs, rhs: op sdiv, inline = true, lhs, rhs:
## 0x05, Signed division ## 0x05, Signed division
push: var r: UInt256
if rhs == 0: zero(Uint256) if rhs != 0:
const min = (1.u256 shl 255) - 1.u256
var a = lhs
var b = rhs
var signA, signB: bool
extractSign(a, signA)
extractSign(b, signB)
if a == min and b == not zero(UInt256):
r = min
else: else:
pseudoSignedToUnsigned( r = a div b
lhs.unsignedToPseudoSigned div rhs.unsignedToPseudoSigned setSign(r, signA xor signB)
) push(r)
op modulo, inline = true, lhs, rhs: op modulo, inline = true, lhs, rhs:
## 0x06, Modulo ## 0x06, Modulo
@ -59,12 +67,17 @@ op modulo, inline = true, lhs, rhs:
op smod, inline = true, lhs, rhs: op smod, inline = true, lhs, rhs:
## 0x07, Signed modulo ## 0x07, Signed modulo
push: var r: UInt256
if rhs == 0: zero(UInt256) if rhs != 0:
else: var sign: bool
pseudoSignedToUnsigned( var v = lhs
lhs.unsignedToPseudoSigned mod rhs.unsignedToPseudoSigned var m = rhs
) extractSign(m, sign)
extractSign(v, sign)
r = v mod m
setSign(r, sign)
push(r)
op addmod, inline = true, lhs, rhs, modulus: op addmod, inline = true, lhs, rhs, modulus:
## 0x08, Modulo addition ## 0x08, Modulo addition
@ -182,6 +195,9 @@ op sha3, inline = true, startPos, length:
computation.memory.extend(pos, len) computation.memory.extend(pos, len)
let endRange = min(pos + len, computation.memory.len) - 1 let endRange = min(pos + len, computation.memory.len) - 1
if endRange == -1:
push(EMPTY_SHA3)
else:
push: push:
keccak256.digest computation.memory.bytes.toOpenArray(pos, endRange) keccak256.digest computation.memory.bytes.toOpenArray(pos, endRange)
@ -421,8 +437,8 @@ op sstore, inline = false, slot, value:
let (currentValue, existing) = computation.vmState.readOnlyStateDB.getStorage(computation.msg.storageAddress, slot) let (currentValue, existing) = computation.vmState.readOnlyStateDB.getStorage(computation.msg.storageAddress, slot)
let let
gasParam = GasParams(kind: Op.Sstore, s_isStorageEmpty: not existing) gasParam = GasParams(kind: Op.Sstore, s_isStorageEmpty: currentValue.isZero)
(gasCost, gasRefund) = computation.gasCosts[Sstore].c_handler(currentValue, gasParam) (gasCost, gasRefund) = computation.gasCosts[Sstore].c_handler(value, gasParam)
computation.gasMeter.consumeGas(gasCost, &"SSTORE: {computation.msg.storageAddress}[{slot}] -> {value} ({currentValue})") computation.gasMeter.consumeGas(gasCost, &"SSTORE: {computation.msg.storageAddress}[{slot}] -> {value} ({currentValue})")

View File

@ -15,16 +15,6 @@ import
func log256*(value: UInt256): Natural {.inline.}= func log256*(value: UInt256): Natural {.inline.}=
(255 - value.countLeadingZeroBits) shr 3 # div 8 (255 - value.countLeadingZeroBits) shr 3 # div 8
func unsignedToPseudoSigned*(value: UInt256): UInt256 {.inline.}=
result = value
if value > INT_256_MAX_AS_UINT256:
result -= INT_256_MAX_AS_UINT256
func pseudoSignedToUnsigned*(value: UInt256): UInt256 {.inline.}=
result = value
if value > INT_256_MAX_AS_UINT256:
result += INT_256_MAX_AS_UINT256
func ceil32*(value: Natural): Natural {.inline.}= func ceil32*(value: Natural): Natural {.inline.}=
# Round input to the nearest bigger multiple of 32 # Round input to the nearest bigger multiple of 32
@ -38,3 +28,16 @@ func wordCount*(length: Natural): Natural {.inline.}=
# Returns the number of EVM words corresponding to a specific size. # Returns the number of EVM words corresponding to a specific size.
# EVM words is rounded up # EVM words is rounded up
length.ceil32 shr 5 # equivalent to `div 32` (32 = 2^5) length.ceil32 shr 5 # equivalent to `div 32` (32 = 2^5)
proc flipSign(value: var UInt256) =
# ⚠ Warning: low(Int256) (binary repr 0b1000...0000) cannot be negated, please handle this special case
value = not value
value += 1.u256
proc extractSign*(v: var UInt256, sign: var bool) =
sign = v > INT_256_MAX_AS_UINT256
if sign:
flipSign(v)
proc setSign*(v: var UInt256, sign: bool) {.inline.} =
if sign: flipSign(v)