research/casper4/sighash.se.py

65 lines
2.6 KiB
Python

# Fetches the char from calldata at position $x
macro calldatachar($x):
div(calldataload($x), 2**248)
# Fetches the next $b bytes from calldata starting at position $x
# Assumes that there is nothing important in memory at bytes 0..63
macro calldatabytes_as_int($x, $b):
~mstore(32-$b, calldataload($x))
~mload(0)
# Position in calldata
with pos = 0:
# First char in calldata
with c0 = calldatachar(0):
# The start of the array must be in 192...255 because it represents
# a list length
# Length ++ body case
if c0 < 248:
pos = 1
# Length of length ++ length ++ body case
else:
pos = (c0 - 246)
# Start position of the list (save it)
with startpos = pos:
# Start position of the previous element
with lastpos = 0:
# Keep looping until we hit the end of the input
while pos < ~calldatasize():
# Next char in calldata
with c = calldatachar(pos):
lastpos = pos
# Single byte 0x00...0x7f body case
if c < 128:
pos += 1
# Length ++ body case
elif c < 184:
pos += c - 127
# Length of length ++ length ++ body case
elif c < 192:
pos += calldatabytes_as_int(pos + 1, c - 183) + (c - 182)
# Length of new RLP list
with newlen = lastpos - startpos:
# Length ++ body case
if newlen < 56:
# Store length in the first byte
~mstore8(0, 192 + newlen)
# Copy calldata right after length
~calldatacopy(1, startpos, newlen)
# Return the hash
return(~sha3(0, 1 + newlen))
else:
# The log256 of the length (ie. length of length)
# Can't go higher than 16777216 bytes due to gas limits
with _log = if(newlen < 256, 1, if(newlen < 65536, 2, 3)):
# Store the length
~mstore(0, newlen)
# Store the length of the length right before the length
with 31minuslog = 31 - _log:
~mstore8(31minuslog, 247 + _log)
# Store the rest of the data
~calldatacopy(32, startpos, newlen)
# Return the hash
return(~sha3(31minuslog, 1 + _log + newlen))