mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 21:34:33 +00:00
implement EIP1014: Create2 opcode
This commit is contained in:
parent
480a3d2cab
commit
5f2be4231e
@ -20,5 +20,21 @@ func keccakHash*(value: openarray[byte]): Hash256 {.inline.} =
|
||||
func generateAddress*(address: EthAddress, nonce: AccountNonce): EthAddress =
|
||||
result[0..19] = keccakHash(rlp.encodeList(address, nonce)).data.toOpenArray(12, 31)
|
||||
|
||||
func generateSafeAddress*(address: EthAddress, salt: Uint256, data: openArray[byte]): EthAddress =
|
||||
const prefix = [0xff.byte]
|
||||
let dataHash = keccakHash(data)
|
||||
var hashResult: Hash256
|
||||
|
||||
var ctx: keccak256
|
||||
ctx.init()
|
||||
ctx.update(prefix)
|
||||
ctx.update(address)
|
||||
ctx.update(salt.toByteArrayBE())
|
||||
ctx.update(dataHash.data)
|
||||
ctx.finish hashResult.data
|
||||
ctx.clear()
|
||||
|
||||
result[0..19] = hashResult.data.toOpenArray(12, 31)
|
||||
|
||||
func hash*(b: BlockHeader): Hash256 {.inline.} =
|
||||
rlpHash(b)
|
||||
|
@ -196,7 +196,7 @@ proc applyMessage*(computation: BaseComputation, opCode: static[Op]) =
|
||||
computation.dispose()
|
||||
|
||||
# EIP161 nonce incrementation
|
||||
when opCode == Create:
|
||||
when opCode in {Create, Create2}:
|
||||
if computation.getFork >= FkSpurious:
|
||||
computation.vmState.mutateStateDb:
|
||||
db.incNonce(computation.msg.storageAddress)
|
||||
|
@ -353,6 +353,10 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) =
|
||||
if gasParams.sd_condition:
|
||||
result.gasCost += static(FeeSchedule[GasNewAccount])
|
||||
|
||||
func `prefix gasCreate2`(currentMemSize, memOffset, memLength: Natural): GasInt {.nimcall.} =
|
||||
result = static(FeeSchedule[GasCreate]) +
|
||||
static(FeeSchedule[GasSha3Word]) * (memLength).wordCount
|
||||
|
||||
# ###################################################################################################
|
||||
|
||||
# TODO - change this `let` into `const` - pending: https://github.com/nim-lang/Nim/issues/8015
|
||||
@ -532,7 +536,7 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) =
|
||||
CallCode: complex `prefix gasCall`,
|
||||
Return: memExpansion `prefix gasHalt`,
|
||||
DelegateCall: complex `prefix gasCall`,
|
||||
Create2: complex `prefix gasCall`,
|
||||
Create2: memExpansion `prefix gasCreate2`,
|
||||
StaticCall: complex `prefix gasCall`,
|
||||
Revert: memExpansion `prefix gasHalt`,
|
||||
Invalid: fixed GasZero,
|
||||
|
@ -503,14 +503,18 @@ genLog()
|
||||
# ##########################################
|
||||
# f0s: System operations.
|
||||
|
||||
proc canTransfer(computation: BaseComputation, memPos, memLen: int, value: Uint256): bool =
|
||||
let gasParams = GasParams(kind: Create,
|
||||
cr_currentMemSize: computation.memory.len,
|
||||
cr_memOffset: memPos,
|
||||
cr_memLength: memLen
|
||||
)
|
||||
let gasCost = computation.gasCosts[Create].c_handler(1.u256, gasParams).gasCost
|
||||
let reason = &"CREATE: GasCreate + {memLen} * memory expansion"
|
||||
proc canTransfer(computation: BaseComputation, memPos, memLen: int, value: Uint256, opCode: static[Op]): bool =
|
||||
when opCode == Create:
|
||||
let gasParams = GasParams(kind: Create,
|
||||
cr_currentMemSize: computation.memory.len,
|
||||
cr_memOffset: memPos,
|
||||
cr_memLength: memLen
|
||||
)
|
||||
let gasCost = computation.gasCosts[Create].c_handler(1.u256, gasParams).gasCost
|
||||
let reason = &"CREATE: GasCreate + {memLen} * memory expansion"
|
||||
else:
|
||||
let gasCost = computation.gasCosts[Create2].m_handler(0, 0, memLen)
|
||||
let reason = &"CREATE2: GasCreate + {memLen} * GasSha3Word"
|
||||
|
||||
computation.gasMeter.consumeGas(gasCost, reason = reason)
|
||||
computation.memory.extend(memPos, memLen)
|
||||
@ -535,7 +539,7 @@ proc canTransfer(computation: BaseComputation, memPos, memLen: int, value: Uint2
|
||||
|
||||
result = true
|
||||
|
||||
proc setupCreate(computation: BaseComputation, memPos, len: int, value: Uint256): BaseComputation =
|
||||
proc setupCreate(computation: BaseComputation, memPos, len: int, value: Uint256, opCode: static[Op]): BaseComputation =
|
||||
let
|
||||
callData = computation.memory.read(memPos, len)
|
||||
|
||||
@ -553,14 +557,20 @@ proc setupCreate(computation: BaseComputation, memPos, len: int, value: Uint256)
|
||||
contractAddress: EthAddress
|
||||
isCollision: bool
|
||||
|
||||
computation.vmState.mutateStateDB:
|
||||
# Regarding collisions, see: https://github.com/status-im/nimbus/issues/133
|
||||
# See: https://github.com/ethereum/EIPs/issues/684
|
||||
let creationNonce = db.getNonce(computation.msg.storageAddress)
|
||||
db.setNonce(computation.msg.storageAddress, creationNonce + 1)
|
||||
when opCode == Create:
|
||||
computation.vmState.mutateStateDB:
|
||||
# Regarding collisions, see: https://github.com/status-im/nimbus/issues/133
|
||||
# See: https://github.com/ethereum/EIPs/issues/684
|
||||
let creationNonce = db.getNonce(computation.msg.storageAddress)
|
||||
db.setNonce(computation.msg.storageAddress, creationNonce + 1)
|
||||
|
||||
contractAddress = generateAddress(computation.msg.storageAddress, creationNonce)
|
||||
isCollision = db.hasCodeOrNonce(contractAddress)
|
||||
contractAddress = generateAddress(computation.msg.storageAddress, creationNonce)
|
||||
isCollision = db.hasCodeOrNonce(contractAddress)
|
||||
else:
|
||||
computation.vmState.mutateStateDB:
|
||||
let salt = computation.stack.popInt()
|
||||
contractAddress = generateSafeAddress(computation.msg.storageAddress, salt, callData)
|
||||
isCollision = db.hasCodeOrNonce(contractAddress)
|
||||
|
||||
if isCollision:
|
||||
debug "Address collision while creating contract", address = contractAddress.toHex
|
||||
@ -585,27 +595,31 @@ proc setupCreate(computation: BaseComputation, memPos, len: int, value: Uint256)
|
||||
childMsg,
|
||||
some(computation.getFork))
|
||||
|
||||
op create, inline = false, value, startPosition, size:
|
||||
## 0xf0, Create a new account with associated code.
|
||||
let (memPos, len) = (startPosition.cleanMemRef, size.cleanMemRef)
|
||||
if not computation.canTransfer(memPos, len, value):
|
||||
push: 0
|
||||
return
|
||||
|
||||
var childComp = setupCreate(computation, memPos, len, value)
|
||||
if childComp.isNil: return
|
||||
|
||||
computation.child = childComp
|
||||
continuation(childComp):
|
||||
computation.addChildComputation(childComp)
|
||||
|
||||
if childComp.isError:
|
||||
template genCreate(callName: untyped, opCode: Op): untyped =
|
||||
op callName, inline = false, value, startPosition, size:
|
||||
## 0xf0, Create a new account with associated code.
|
||||
let (memPos, len) = (startPosition.cleanMemRef, size.cleanMemRef)
|
||||
if not computation.canTransfer(memPos, len, value, opCode):
|
||||
push: 0
|
||||
else:
|
||||
push: childComp.msg.storageAddress
|
||||
return
|
||||
|
||||
checkInStaticContext(computation)
|
||||
childComp.applyMessage(Create)
|
||||
var childComp = setupCreate(computation, memPos, len, value, opCode)
|
||||
if childComp.isNil: return
|
||||
|
||||
computation.child = childComp
|
||||
continuation(childComp):
|
||||
addChildComputation(computation, childComp)
|
||||
|
||||
if childComp.isError:
|
||||
push: 0
|
||||
else:
|
||||
push: childComp.msg.storageAddress
|
||||
|
||||
checkInStaticContext(computation)
|
||||
childComp.applyMessage(Create)
|
||||
|
||||
genCreate(create, Create)
|
||||
genCreate(create2, Create2)
|
||||
|
||||
proc callParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, EthAddress, EthAddress, UInt256, UInt256, UInt256, UInt256, MsgFlags) =
|
||||
let gas = computation.stack.popInt()
|
||||
@ -909,7 +923,3 @@ op extCodeHash, inline = true:
|
||||
push: 0
|
||||
else:
|
||||
push: computation.vmState.readOnlyStateDB.getCodeHash(address)
|
||||
|
||||
op create2, inline = false:
|
||||
# TODO: implementation
|
||||
discard
|
||||
|
Loading…
x
Reference in New Issue
Block a user