constantinople's skeletal implementation

This commit is contained in:
andri lim 2019-04-30 12:23:51 +07:00 committed by zah
parent b45e9d5493
commit 213fb3b971
6 changed files with 71 additions and 13 deletions

View File

@ -48,7 +48,9 @@ type
GasSha3, # Paid for each SHA3 operation.
GasSha3Word, # Paid for each word (rounded up) for input data to a SHA3 operation.
GasCopy, # Partial payment for COPY operations, multiplied by words copied, rounded up.
GasBlockhash # Payment for BLOCKHASH operation.
GasBlockhash, # Payment for BLOCKHASH operation.
GasArithmetic, # Payment for bitwise Shl and Shr operators
GasExtCodeHash # Payment for contract's code hashing
GasFeeSchedule = array[GasFeeKind, GasInt]
@ -400,6 +402,9 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) =
Xor: fixed GasVeryLow,
Not: fixed GasVeryLow,
Byte: fixed GasVeryLow,
Shl: fixed GasArithmetic,
Shr: fixed GasArithmetic,
Sar: fixed GasVeryLow,
# 20s: SHA3
Sha3: memExpansion `prefix gasSha3`,
@ -420,6 +425,7 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) =
ExtCodeCopy: memExpansion `prefix gasExtCodeCopy`,
ReturnDataSize: fixed GasBase,
ReturnDataCopy: memExpansion `prefix gasCopy`,
ExtCodeHash: fixed GasExtCodeHash,
# 40s: Block Information
Blockhash: fixed GasBlockhash,
@ -526,6 +532,7 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) =
CallCode: complex `prefix gasCall`,
Return: memExpansion `prefix gasHalt`,
DelegateCall: complex `prefix gasCall`,
Create2: complex `prefix gasCall`,
StaticCall: complex `prefix gasCall`,
Revert: memExpansion `prefix gasHalt`,
Invalid: fixed GasZero,
@ -570,7 +577,9 @@ const
GasSha3: 30,
GasSha3Word: 6,
GasCopy: 3,
GasBlockhash: 20
GasBlockhash: 20,
GasArithmetic: 35,
GasExtCodeHash: 400
]
# Create the schedule for each forks
@ -605,7 +614,8 @@ const
FkDao: HomesteadGasFees,
FkTangerine: TangerineGasFees,
FkSpurious: SpuriousGasFees,
FkByzantium: SpuriousGasFees, # not supported yet
FkByzantium: SpuriousGasFees,
FkConstantinople: SpuriousGasFees
]

View File

@ -46,6 +46,9 @@ fill_enum_holes:
Xor = 0x18, # Bitwise XOR operation.
Not = 0x19, # Bitwise NOT operation.
Byte = 0x1A, # Retrieve single byte from word.
Shl = 0x1B, # Shift left
Shr = 0x1C, # Logical shift right
Sar = 0x1D, # Arithmetic shift right
# 20s: SHA3
Sha3 = 0x20, # Compute Keccak-256 hash.
@ -66,6 +69,7 @@ fill_enum_holes:
ExtCodeCopy = 0x3c, # Copy an account's code to memory.
ReturnDataSize = 0x3d, # Get size of output data from the previous call from the current environment.
ReturnDataCopy = 0x3e, # Copy output data from the previous call to memory.
ExtCodeHash = 0x3f, # Returns the keccak256 hash of a contracts code
# 40s: Block Information
Blockhash = 0x40, # Get the hash of one of the 256 most recent complete blocks.
@ -172,6 +176,7 @@ fill_enum_holes:
CallCode = 0xf2, # Message-call into this account with an alternative account's code.
Return = 0xf3, # Halt execution returning output data.
DelegateCall = 0xf4, # Message-call into this account with an alternative account's code, but persisting the current values for sender and value.
Create2 = 0xf5, # Behaves identically to CREATE, except using keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]
StaticCall = 0xfa, # Static message-call into an account.
Revert = 0xfd, # Halt execution reverting state changes but returning data and remaining gas.
Invalid = 0xfe, # Designated invalid instruction.

View File

@ -881,3 +881,24 @@ op selfDestructEip161, inline = false:
let gasCost = computation.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
computation.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP161")
selfDestructImpl(computation, beneficiary)
# Constantinople's new opcodes
op shlOp, inline = true, num, shift:
# TODO: implementation
discard
op shrOp, inline = true, num, shift:
# TODO: implementation
discard
op sarOp, inline = true, num, shift:
# TODO: implementation
discard
op extCodeHash, inline = true, address:
# TODO: implementation
discard
op create2, inline = false:
# TODO: implementation
discard

View File

@ -15,17 +15,19 @@ type
FkDao,
FkTangerine,
FkSpurious,
FkByzantium
FkByzantium,
FkConstantinople
const
forkBlocks*: array[Fork, Uint256] = [
FkFrontier: 1.u256, # 30/07/2015 19:26:28
FkThawing: 200_000.u256, # 08/09/2015 01:33:09
FkHomestead: 1_150_000.u256, # 14/03/2016 20:49:53
FkDao: 1_920_000.u256, # 20/07/2016 17:20:40
FkTangerine: 2_463_000.u256, # 18/10/2016 17:19:31
FkSpurious: 2_675_000.u256, # 22/11/2016 18:15:44
FkByzantium: 4_370_000.u256 # 16/10/2017 09:22:11
FkFrontier: 1.u256, # 30/07/2015 19:26:28
FkThawing: 200_000.u256, # 08/09/2015 01:33:09
FkHomestead: 1_150_000.u256, # 14/03/2016 20:49:53
FkDao: 1_920_000.u256, # 20/07/2016 17:20:40
FkTangerine: 2_463_000.u256, # 18/10/2016 17:19:31
FkSpurious: 2_675_000.u256, # 22/11/2016 18:15:44
FkByzantium: 4_370_000.u256, # 16/10/2017 09:22:11
FkConstantinople: 7_280_000.u256 # 28/02/2019 07:52:04
]
proc toFork*(blockNumber: UInt256): Fork =
@ -44,8 +46,8 @@ proc toFork*(blockNumber: UInt256): Fork =
elif blockNumber < forkBlocks[FkTangerine]: FkDao
elif blockNumber < forkBlocks[FkSpurious]: FkTangerine
elif blockNumber < forkBlocks[FkByzantium]: FkSpurious
else:
FkByzantium # Update for constantinople when announced
elif blockNumber < forkBlocks[FkConstantinople]: FkByzantium
else: FkConstantinople
proc `$`*(fork: Fork): string =
case fork
@ -56,4 +58,5 @@ proc `$`*(fork: Fork): string =
of FkTangerine: result = "Tangerine Whistle"
of FkSpurious: result = "Spurious Dragon"
of FkByzantium: result = "Byzantium"
of FkConstantinople: result = "Constantinople"

View File

@ -205,6 +205,16 @@ proc genByzantiumJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compil
let ByzantiumOpDispatch {.compileTime.}: array[Op, NimNode] = genByzantiumJumpTable(SpuriousOpDispatch)
proc genConstantinopleJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} =
result = ops
result[Shl] = newIdentNode "shlOp"
result[Shr] = newIdentNode "shrOp"
result[Sar] = newIdentNode "sarOp"
result[ExtCodeHash] = newIdentNode "extCodeHash"
result[Create2] = newIdentNode "create2"
let ConstantinopleOpDispatch {.compileTime.}: array[Op, NimNode] = genConstantinopleJumpTable(ByzantiumOpDispatch)
proc opTableToCaseStmt(opTable: array[Op, NimNode], computation: NimNode): NimNode =
let instr = quote do: `computation`.instr
@ -275,6 +285,9 @@ macro genSpuriousDispatch(computation: BaseComputation): untyped =
macro genByzantiumDispatch(computation: BaseComputation): untyped =
result = opTableToCaseStmt(ByzantiumOpDispatch, computation)
macro genConstantinopleDispatch(computation: BaseComputation): untyped =
result = opTableToCaseStmt(ConstantinopleOpDispatch, computation)
proc frontierVM(computation: BaseComputation) =
genFrontierDispatch(computation)
@ -290,6 +303,9 @@ proc spuriousVM(computation: BaseComputation) {.gcsafe.} =
proc byzantiumVM(computation: BaseComputation) {.gcsafe.} =
genByzantiumDispatch(computation)
proc constantinopleVM(computation: BaseComputation) {.gcsafe.} =
genConstantinopleDispatch(computation)
proc selectVM(computation: BaseComputation, fork: Fork) {.gcsafe.} =
# TODO: Optimise getting fork and updating opCodeExec only when necessary
case fork
@ -303,6 +319,8 @@ proc selectVM(computation: BaseComputation, fork: Fork) {.gcsafe.} =
computation.spuriousVM()
of FKByzantium:
computation.byzantiumVM()
else:
computation.constantinopleVM()
proc executeOpcodes(computation: BaseComputation) =
try:

View File

@ -21,6 +21,7 @@ const
FkTangerine: "EIP150",
FkSpurious: "EIP158",
FkByzantium: "Byzantium",
FkConstantinople: "ConstantinopleFix"
}.toTable
supportedForks* = {FkFrontier, FkHomestead, FkTangerine, FkSpurious, FkByzantium}