Implement EIP-7002 and EIP-7251 (#2616)

This commit is contained in:
andri lim 2024-09-12 13:56:13 +07:00 committed by jangko
parent 6503d51b44
commit 178d77ab31
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
7 changed files with 144 additions and 2 deletions

View File

@ -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

View File

@ -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()
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -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,
@ -187,6 +189,86 @@ 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

View File

@ -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".}

View File

@ -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)

View File

@ -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:

View File

@ -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