Implement EIP-7002 and EIP-7251 (#2616)
This commit is contained in:
parent
6503d51b44
commit
178d77ab31
|
@ -109,4 +109,6 @@ const
|
||||||
|
|
||||||
HISTORY_STORAGE_ADDRESS* = hexToByteArray[20]("0x0aae40965e6800cd9b1f4b05ff21581047e3f91e")
|
HISTORY_STORAGE_ADDRESS* = hexToByteArray[20]("0x0aae40965e6800cd9b1f4b05ff21581047e3f91e")
|
||||||
DEPOSIT_CONTRACT_ADDRESS* = hexToByteArray[20]("0x00000000219ab540356cbb839cbe05303d7705fa")
|
DEPOSIT_CONTRACT_ADDRESS* = hexToByteArray[20]("0x00000000219ab540356cbb839cbe05303d7705fa")
|
||||||
|
WITHDRAWAL_REQUEST_ADDRESS* = hexToByteArray[20]("0x00A3ca265EBcb825B45F985A16CEFB49958cE017")
|
||||||
|
CONSOLIDATION_REQUEST_ADDRESS* = hexToByteArray[20]("0x00b42dbF2194e931E80326D950320f7d9Dbeac02")
|
||||||
# End
|
# End
|
||||||
|
|
|
@ -193,6 +193,23 @@ proc procBlkEpilogue(
|
||||||
expectedDeposits.add req
|
expectedDeposits.add req
|
||||||
if depositReqs != expectedDeposits:
|
if depositReqs != expectedDeposits:
|
||||||
return err("EIP-6110 deposit requests mismatch")
|
return err("EIP-6110 deposit requests mismatch")
|
||||||
|
|
||||||
|
let withdrawalReqs = processDequeueWithdrawalRequests(vmState)
|
||||||
|
var expectedWithdrawals: seq[Request]
|
||||||
|
for req in blk.requests.get:
|
||||||
|
if req.requestType == WithdrawalRequestType:
|
||||||
|
expectedWithdrawals.add req
|
||||||
|
if withdrawalReqs != expectedWithdrawals:
|
||||||
|
return err("EIP-7002 withdrawal requests mismatch")
|
||||||
|
|
||||||
|
let consolidationReqs = processDequeueConsolidationRequests(vmState)
|
||||||
|
var expectedConsolidations: seq[Request]
|
||||||
|
for req in blk.requests.get:
|
||||||
|
if req.requestType == ConsolidationRequestType:
|
||||||
|
expectedConsolidations.add req
|
||||||
|
if consolidationReqs != expectedConsolidations:
|
||||||
|
return err("EIP-7251 consolidation requests mismatch")
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
import
|
import
|
||||||
std/strformat,
|
std/strformat,
|
||||||
results,
|
results,
|
||||||
|
stew/arrayops,
|
||||||
|
stew/endians2,
|
||||||
../../common/common,
|
../../common/common,
|
||||||
../../db/ledger,
|
../../db/ledger,
|
||||||
../../transaction/call_evm,
|
../../transaction/call_evm,
|
||||||
|
@ -159,7 +161,7 @@ proc processBeaconBlockRoot*(vmState: BaseVMState, beaconRoot: Hash256):
|
||||||
|
|
||||||
proc processParentBlockHash*(vmState: BaseVMState, prevHash: Hash256):
|
proc processParentBlockHash*(vmState: BaseVMState, prevHash: Hash256):
|
||||||
Result[void, string] =
|
Result[void, string] =
|
||||||
## processParentBlockHash stores the parent block hash in the
|
## processParentBlockHash stores the parent block hash in the
|
||||||
## history storage contract as per EIP-2935.
|
## history storage contract as per EIP-2935.
|
||||||
let
|
let
|
||||||
statedb = vmState.stateDB
|
statedb = vmState.stateDB
|
||||||
|
@ -186,7 +188,87 @@ proc processParentBlockHash*(vmState: BaseVMState, prevHash: Hash256):
|
||||||
|
|
||||||
statedb.persist(clearEmptyAccount = true)
|
statedb.persist(clearEmptyAccount = true)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
func parseWithdrawalRequest(data: openArray[byte]): WithdrawalRequest =
|
||||||
|
template copyFrom(T: type, input, a, b): auto =
|
||||||
|
T.initCopyFrom(input.toOpenArray(a, b))
|
||||||
|
WithdrawalRequest(
|
||||||
|
sourceAddress: array[20, byte].copyFrom(data, 0, 19),
|
||||||
|
validatorPubkey: array[48, byte].copyFrom(data, 20, 20+47),
|
||||||
|
amount: uint64.fromBytesLE(data.toOpenArray(68, 68+7)),
|
||||||
|
)
|
||||||
|
|
||||||
|
proc processDequeueWithdrawalRequests*(vmState: BaseVMState): seq[Request] =
|
||||||
|
## processDequeueWithdrawalRequests applies the EIP-7002 system call
|
||||||
|
## to the withdrawal requests contract.
|
||||||
|
let
|
||||||
|
statedb = vmState.stateDB
|
||||||
|
call = CallParams(
|
||||||
|
vmState : vmState,
|
||||||
|
sender : SYSTEM_ADDRESS,
|
||||||
|
gasLimit : 30_000_000.GasInt,
|
||||||
|
gasPrice : 0.GasInt,
|
||||||
|
to : WITHDRAWAL_REQUEST_ADDRESS,
|
||||||
|
|
||||||
|
# It's a systemCall, no need for other knicks knacks
|
||||||
|
sysCall : true,
|
||||||
|
noAccessList: true,
|
||||||
|
noIntrinsic : true,
|
||||||
|
noGasCharge : true,
|
||||||
|
noRefund : true,
|
||||||
|
)
|
||||||
|
|
||||||
|
# runComputation a.k.a syscall/evm.call
|
||||||
|
let res = call.runComputation(Blob)
|
||||||
|
statedb.persist(clearEmptyAccount = true)
|
||||||
|
|
||||||
|
for i in 0..<res.len div 76:
|
||||||
|
let start = i * 76
|
||||||
|
result.add Request(
|
||||||
|
requestType: WithdrawalRequestType,
|
||||||
|
withdrawal: parseWithdrawalRequest(res.toOpenArray(i, i + 75))
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseConsolidationRequest(data: openArray[byte]): ConsolidationRequest =
|
||||||
|
template copyFrom(T: type, input, a, b): auto =
|
||||||
|
T.initCopyFrom(input.toOpenArray(a, b))
|
||||||
|
ConsolidationRequest(
|
||||||
|
sourceAddress: array[20, byte].copyFrom(data, 0, 19),
|
||||||
|
sourcePubkey: array[48, byte].copyFrom(data, 20, 20+47),
|
||||||
|
targetPubkey: array[48, byte].copyFrom(data, 68, 68+47),
|
||||||
|
)
|
||||||
|
|
||||||
|
proc processDequeueConsolidationRequests*(vmState: BaseVMState): seq[Request] =
|
||||||
|
## processDequeueConsolidationRequests applies the EIP-7251 system call
|
||||||
|
## to the consolidation requests contract.
|
||||||
|
let
|
||||||
|
statedb = vmState.stateDB
|
||||||
|
call = CallParams(
|
||||||
|
vmState : vmState,
|
||||||
|
sender : SYSTEM_ADDRESS,
|
||||||
|
gasLimit : 30_000_000.GasInt,
|
||||||
|
gasPrice : 0.GasInt,
|
||||||
|
to : CONSOLIDATION_REQUEST_ADDRESS,
|
||||||
|
|
||||||
|
# It's a systemCall, no need for other knicks knacks
|
||||||
|
sysCall : true,
|
||||||
|
noAccessList: true,
|
||||||
|
noIntrinsic : true,
|
||||||
|
noGasCharge : true,
|
||||||
|
noRefund : true,
|
||||||
|
)
|
||||||
|
|
||||||
|
# runComputation a.k.a syscall/evm.call
|
||||||
|
let res = call.runComputation(Blob)
|
||||||
|
statedb.persist(clearEmptyAccount = true)
|
||||||
|
|
||||||
|
for i in 0..<res.len div 116:
|
||||||
|
let start = i * 116
|
||||||
|
result.add Request(
|
||||||
|
requestType: ConsolidationRequestType,
|
||||||
|
consolidation: parseConsolidationRequest(res.toOpenArray(i, i + 115))
|
||||||
|
)
|
||||||
|
|
||||||
proc processTransaction*(
|
proc processTransaction*(
|
||||||
vmState: BaseVMState; ## Parent accounts environment for transaction
|
vmState: BaseVMState; ## Parent accounts environment for transaction
|
||||||
tx: Transaction; ## Transaction to validate
|
tx: Transaction; ## Transaction to validate
|
||||||
|
|
|
@ -300,6 +300,8 @@ proc finishRunningComputation(
|
||||||
elif T is string:
|
elif T is string:
|
||||||
if c.isError:
|
if c.isError:
|
||||||
result = c.error.info
|
result = c.error.info
|
||||||
|
elif T is Blob:
|
||||||
|
result = move(c.output)
|
||||||
else:
|
else:
|
||||||
{.error: "Unknown computation output".}
|
{.error: "Unknown computation output".}
|
||||||
|
|
||||||
|
|
|
@ -412,6 +412,20 @@ proc `@@`(x: DepositRequest): JsonNode =
|
||||||
"index": @@(x.index),
|
"index": @@(x.index),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc `@@`(x: WithdrawalRequest): JsonNode =
|
||||||
|
%{
|
||||||
|
"sourceAddress": @@(x.sourceAddress),
|
||||||
|
"validatorPubkey": @@(x.validatorPubkey),
|
||||||
|
"amount": @@(x.amount),
|
||||||
|
}
|
||||||
|
|
||||||
|
proc `@@`(x: ConsolidationRequest): JsonNode =
|
||||||
|
%{
|
||||||
|
"sourceAddress": @@(x.sourceAddress),
|
||||||
|
"sourcePubkey": @@(x.sourcePubkey),
|
||||||
|
"targetPubkey": @@(x.targetPubkey),
|
||||||
|
}
|
||||||
|
|
||||||
proc `@@`[T](x: seq[T]): JsonNode =
|
proc `@@`[T](x: seq[T]): JsonNode =
|
||||||
result = newJArray()
|
result = newJArray()
|
||||||
for c in x:
|
for c in x:
|
||||||
|
@ -448,3 +462,7 @@ proc `@@`*(x: ExecutionResult): JsonNode =
|
||||||
result["requestsRoot"] = @@(x.requestsRoot)
|
result["requestsRoot"] = @@(x.requestsRoot)
|
||||||
if x.depositRequests.isSome:
|
if x.depositRequests.isSome:
|
||||||
result["depositRequests"] = @@(x.depositRequests)
|
result["depositRequests"] = @@(x.depositRequests)
|
||||||
|
if x.withdrawalRequests.isSome:
|
||||||
|
result["withdrawalRequests"] = @@(x.withdrawalRequests)
|
||||||
|
if x.consolidationRequests.isSome:
|
||||||
|
result["consolidationRequests"] = @@(x.consolidationRequests)
|
||||||
|
|
|
@ -314,6 +314,15 @@ proc exec(ctx: var TransContext,
|
||||||
let miner = ctx.env.currentCoinbase
|
let miner = ctx.env.currentCoinbase
|
||||||
coinbaseStateClearing(vmState, miner, stateReward.isSome())
|
coinbaseStateClearing(vmState, miner, stateReward.isSome())
|
||||||
|
|
||||||
|
var
|
||||||
|
withdrawalReqs: seq[Request]
|
||||||
|
consolidationReqs: seq[Request]
|
||||||
|
|
||||||
|
if vmState.com.isPragueOrLater(ctx.env.currentTimestamp):
|
||||||
|
# Execute EIP-7002 and EIP-7251 before calculating rootHash
|
||||||
|
withdrawalReqs = processDequeueWithdrawalRequests(vmState)
|
||||||
|
consolidationReqs = processDequeueConsolidationRequests(vmState)
|
||||||
|
|
||||||
let stateDB = vmState.stateDB
|
let stateDB = vmState.stateDB
|
||||||
stateDB.postState(result.alloc)
|
stateDB.postState(result.alloc)
|
||||||
result.result = ExecutionResult(
|
result.result = ExecutionResult(
|
||||||
|
@ -353,6 +362,16 @@ proc exec(ctx: var TransContext,
|
||||||
deposits.add req.deposit
|
deposits.add req.deposit
|
||||||
result.result.depositRequests = Opt.some(deposits)
|
result.result.depositRequests = Opt.some(deposits)
|
||||||
|
|
||||||
|
var withdrawals: seq[WithdrawalRequest]
|
||||||
|
for req in withdrawalReqs:
|
||||||
|
withdrawals.add req.withdrawal
|
||||||
|
result.result.withdrawalRequests = Opt.some(withdrawals)
|
||||||
|
|
||||||
|
var consolidations: seq[ConsolidationRequest]
|
||||||
|
for req in consolidationReqs:
|
||||||
|
consolidations.add req.consolidation
|
||||||
|
result.result.consolidationRequests = Opt.some(consolidations)
|
||||||
|
|
||||||
template wrapException(body: untyped) =
|
template wrapException(body: untyped) =
|
||||||
when wrapExceptionEnabled:
|
when wrapExceptionEnabled:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -101,6 +101,8 @@ type
|
||||||
currentExcessBlobGas*: Opt[uint64]
|
currentExcessBlobGas*: Opt[uint64]
|
||||||
requestsRoot*: Opt[Hash256]
|
requestsRoot*: Opt[Hash256]
|
||||||
depositRequests*: Opt[seq[DepositRequest]]
|
depositRequests*: Opt[seq[DepositRequest]]
|
||||||
|
withdrawalRequests*: Opt[seq[WithdrawalRequest]]
|
||||||
|
consolidationRequests*: Opt[seq[ConsolidationRequest]]
|
||||||
|
|
||||||
const
|
const
|
||||||
ErrorEVM* = 2.T8NExitCode
|
ErrorEVM* = 2.T8NExitCode
|
||||||
|
|
Loading…
Reference in New Issue