122 lines
3.8 KiB
Nim
122 lines
3.8 KiB
Nim
# Fluffy
|
|
# Copyright (c) 2024 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
{.push raises: [].}
|
|
|
|
import
|
|
chronicles,
|
|
stew/byteutils,
|
|
stint,
|
|
eth/common/base,
|
|
../../../rpc/rpc_calls/rpc_trace_calls,
|
|
../portal_bridge_common
|
|
|
|
type
|
|
DiffType* = enum
|
|
unchanged
|
|
create
|
|
update
|
|
delete
|
|
|
|
Code = seq[byte]
|
|
StateValue* = UInt256 | AccountNonce | Code
|
|
|
|
StateValueDiff*[StateValue] = object
|
|
kind*: DiffType
|
|
before*: StateValue
|
|
after*: StateValue
|
|
|
|
SlotDiff* = tuple[slotKey: UInt256, slotValueDiff: StateValueDiff[UInt256]]
|
|
|
|
AccountDiff* = object
|
|
address*: Address
|
|
balanceDiff*: StateValueDiff[UInt256]
|
|
nonceDiff*: StateValueDiff[AccountNonce]
|
|
storageDiff*: seq[SlotDiff]
|
|
codeDiff*: StateValueDiff[Code]
|
|
|
|
TransactionDiff* = seq[AccountDiff]
|
|
|
|
proc toStateValue(T: type UInt256, hex: string): T {.raises: [ValueError].} =
|
|
UInt256.fromHex(hex)
|
|
|
|
proc toStateValue(T: type AccountNonce, hex: string): T {.raises: [ValueError].} =
|
|
UInt256.fromHex(hex).truncate(uint64)
|
|
|
|
proc toStateValue(T: type Code, hex: string): T {.raises: [ValueError].} =
|
|
hexToSeqByte(hex)
|
|
|
|
proc toStateValueDiff(
|
|
diffJson: JsonNode, T: type StateValue
|
|
): StateValueDiff[T] {.raises: [ValueError].} =
|
|
if diffJson.kind == JString and diffJson.getStr() == "=":
|
|
return StateValueDiff[T](kind: unchanged)
|
|
elif diffJson.kind == JObject:
|
|
if diffJson{"+"} != nil:
|
|
return
|
|
StateValueDiff[T](kind: create, after: T.toStateValue(diffJson{"+"}.getStr()))
|
|
elif diffJson{"-"} != nil:
|
|
return
|
|
StateValueDiff[T](kind: delete, before: T.toStateValue(diffJson{"-"}.getStr()))
|
|
elif diffJson{"*"} != nil:
|
|
return StateValueDiff[T](
|
|
kind: update,
|
|
before: T.toStateValue(diffJson{"*"}{"from"}.getStr()),
|
|
after: T.toStateValue(diffJson{"*"}{"to"}.getStr()),
|
|
)
|
|
else:
|
|
doAssert false # unreachable
|
|
else:
|
|
doAssert false # unreachable
|
|
|
|
proc toTransactionDiff(
|
|
stateDiffJson: JsonNode
|
|
): TransactionDiff {.raises: [ValueError].} =
|
|
var txDiff = newSeqOfCap[AccountDiff](stateDiffJson.len())
|
|
|
|
for addrJson, accJson in stateDiffJson:
|
|
let storageDiffJson = accJson["storage"]
|
|
var storageDiff = newSeqOfCap[SlotDiff](storageDiffJson.len())
|
|
|
|
for slotKeyJson, slotValueJson in storageDiffJson:
|
|
storageDiff.add(
|
|
(UInt256.fromHex(slotKeyJson), toStateValueDiff(slotValueJson, UInt256))
|
|
)
|
|
|
|
let accountDiff = AccountDiff(
|
|
address: Address.fromHex(addrJson),
|
|
balanceDiff: toStateValueDiff(accJson["balance"], UInt256),
|
|
nonceDiff: toStateValueDiff(accJson["nonce"], AccountNonce),
|
|
storageDiff: storageDiff,
|
|
codeDiff: toStateValueDiff(accJson["code"], Code),
|
|
)
|
|
txDiff.add(accountDiff)
|
|
|
|
txDiff
|
|
|
|
proc toTransactionDiffs(
|
|
blockTraceJson: JsonNode
|
|
): seq[TransactionDiff] {.raises: [ValueError].} =
|
|
var txDiffs = newSeqOfCap[TransactionDiff](blockTraceJson.len())
|
|
for blockTrace in blockTraceJson:
|
|
txDiffs.add(blockTrace["stateDiff"].toTransactionDiff())
|
|
|
|
txDiffs
|
|
|
|
proc getStateDiffsByBlockNumber*(
|
|
client: RpcClient, blockId: BlockIdentifier
|
|
): Future[Result[seq[TransactionDiff], string]] {.async: (raises: []).} =
|
|
const traceOpts = @["stateDiff"]
|
|
|
|
try:
|
|
let blockTraceJson = await client.trace_replayBlockTransactions(blockId, traceOpts)
|
|
if blockTraceJson.isNil:
|
|
return err("EL failed to provide requested state diff")
|
|
ok(blockTraceJson.toTransactionDiffs())
|
|
except CatchableError as e:
|
|
return err("EL JSON-RPC trace_replayBlockTransactions failed: " & e.msg)
|