mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-26 03:59:52 +00:00
fix t8n tool tx and env parser
This commit is contained in:
parent
ed518c760f
commit
490b2f8023
@ -10,13 +10,14 @@
|
|||||||
|
|
||||||
import
|
import
|
||||||
std/[json, strutils, tables],
|
std/[json, strutils, tables],
|
||||||
stew/byteutils,
|
stew/[byteutils, results],
|
||||||
stint,
|
stint,
|
||||||
eth/[common, rlp, keys],
|
eth/[common, rlp, keys],
|
||||||
../../nimbus/transaction,
|
../../nimbus/transaction,
|
||||||
../../nimbus/common/chain_config,
|
../../nimbus/common/chain_config,
|
||||||
../common/helpers,
|
../common/helpers,
|
||||||
./types
|
./types,
|
||||||
|
./txpriv
|
||||||
|
|
||||||
export
|
export
|
||||||
helpers
|
helpers
|
||||||
@ -150,6 +151,9 @@ proc parseEnv*(ctx: var TransContext, n: JsonNode) =
|
|||||||
omitZero(ctx.env, EthTime, parentTimestamp)
|
omitZero(ctx.env, EthTime, parentTimestamp)
|
||||||
optional(ctx.env, UInt256, currentBaseFee)
|
optional(ctx.env, UInt256, currentBaseFee)
|
||||||
omitZero(ctx.env, Hash256, parentUncleHash)
|
omitZero(ctx.env, Hash256, parentUncleHash)
|
||||||
|
optional(ctx.env, UInt256, parentBaseFee)
|
||||||
|
optional(ctx.env, GasInt, parentGasUsed)
|
||||||
|
optional(ctx.env, GasInt, parentGasLimit)
|
||||||
|
|
||||||
if n.hasKey("blockHashes"):
|
if n.hasKey("blockHashes"):
|
||||||
let w = n["blockHashes"]
|
let w = n["blockHashes"]
|
||||||
@ -203,24 +207,79 @@ proc parseTx(n: JsonNode, chainId: ChainID): Transaction =
|
|||||||
else:
|
else:
|
||||||
tx
|
tx
|
||||||
|
|
||||||
proc parseTxs*(ctx: var TransContext, txs: JsonNode, chainId: ChainID) =
|
proc parseTxLegacy(item: var Rlp): Result[Transaction, string] =
|
||||||
|
try:
|
||||||
|
var tx: Transaction
|
||||||
|
item.readTxLegacy(tx)
|
||||||
|
return ok(tx)
|
||||||
|
except RlpError as x:
|
||||||
|
return err(x.msg)
|
||||||
|
|
||||||
|
proc parseTxTyped(item: var Rlp): Result[Transaction, string] =
|
||||||
|
try:
|
||||||
|
var tx: Transaction
|
||||||
|
var rr = rlpFromBytes(item.read(Blob))
|
||||||
|
rr.readTxTyped(tx)
|
||||||
|
return ok(tx)
|
||||||
|
except RlpError as x:
|
||||||
|
return err(x.msg)
|
||||||
|
|
||||||
|
proc parseTxJson(ctx: TransContext, i: int, chainId: ChainId): Result[Transaction, string] =
|
||||||
|
try:
|
||||||
|
let n = ctx.txs.n[i]
|
||||||
|
return ok(parseTx(n, chainId))
|
||||||
|
except Exception as x:
|
||||||
|
return err(x.msg)
|
||||||
|
|
||||||
|
proc parseTxs*(ctx: TransContext, chainId: ChainId): seq[Result[Transaction, string]] =
|
||||||
|
if ctx.txs.txsType == TxsJson:
|
||||||
|
let len = ctx.txs.n.len
|
||||||
|
result = newSeqOfCap[Result[Transaction, string]](len)
|
||||||
|
for i in 0 ..< len:
|
||||||
|
result.add ctx.parseTxJson(i, chainId)
|
||||||
|
return
|
||||||
|
|
||||||
|
if ctx.txs.txsType == TxsRlp:
|
||||||
|
result = newSeqOfCap[Result[Transaction, string]](ctx.txs.r.listLen)
|
||||||
|
var rlp = ctx.txs.r
|
||||||
|
for item in rlp:
|
||||||
|
if item.isList:
|
||||||
|
result.add parseTxLegacy(item)
|
||||||
|
else:
|
||||||
|
result.add parseTxTyped(item)
|
||||||
|
return
|
||||||
|
|
||||||
|
proc txList*(ctx: TransContext, chainId: ChainId): seq[Transaction] =
|
||||||
|
let list = ctx.parseTxs(chainId)
|
||||||
|
for txRes in list:
|
||||||
|
if txRes.isOk:
|
||||||
|
result.add txRes.get
|
||||||
|
|
||||||
|
proc parseTxs*(ctx: var TransContext, txs: JsonNode) =
|
||||||
if txs.kind == JNull:
|
if txs.kind == JNull:
|
||||||
return
|
return
|
||||||
if txs.kind != JArray:
|
if txs.kind != JArray:
|
||||||
raise newError(ErrorJson, "Transaction list should be a JSON array, got=" & $txs.kind)
|
raise newError(ErrorJson,
|
||||||
for n in txs:
|
"Transaction list should be a JSON array, got=" & $txs.kind)
|
||||||
ctx.txs.add parseTx(n, chainId)
|
ctx.txs = TxsList(
|
||||||
|
txsType: TxsJson,
|
||||||
|
n: txs)
|
||||||
|
|
||||||
proc parseTxsRlp*(ctx: var TransContext, hexData: string) =
|
proc parseTxsRlp*(ctx: var TransContext, hexData: string) =
|
||||||
let data = hexToSeqByte(hexData)
|
let bytes = hexToSeqByte(hexData)
|
||||||
ctx.txs = rlp.decode(data, seq[Transaction])
|
ctx.txs = TxsList(
|
||||||
|
txsType: TxsRlp,
|
||||||
|
r: rlpFromBytes(bytes)
|
||||||
|
)
|
||||||
|
if ctx.txs.r.isList.not:
|
||||||
|
raise newError(ErrorRlp, "RLP Transaction list should be a list")
|
||||||
|
|
||||||
proc parseInputFromStdin*(ctx: var TransContext, chainId: ChainId) =
|
proc parseInputFromStdin*(ctx: var TransContext) =
|
||||||
let data = stdin.readAll()
|
let data = stdin.readAll()
|
||||||
let n = json.parseJson(data)
|
let n = json.parseJson(data)
|
||||||
if n.hasKey("alloc"): ctx.parseAlloc(n["alloc"])
|
if n.hasKey("alloc"): ctx.parseAlloc(n["alloc"])
|
||||||
if n.hasKey("env"): ctx.parseEnv(n["env"])
|
if n.hasKey("env"): ctx.parseEnv(n["env"])
|
||||||
if n.hasKey("txs"): ctx.parseTxs(n["txs"], chainId)
|
if n.hasKey("txs"): ctx.parseTxs(n["txs"])
|
||||||
if n.hasKey("txsRlp"): ctx.parseTxsRlp(n["txsRlp"].getStr())
|
if n.hasKey("txsRlp"): ctx.parseTxsRlp(n["txsRlp"].getStr())
|
||||||
|
|
||||||
template stripLeadingZeros(value: string): string =
|
template stripLeadingZeros(value: string): string =
|
||||||
@ -336,3 +395,5 @@ proc `@@`*(x: ExecutionResult): JsonNode =
|
|||||||
}
|
}
|
||||||
if x.rejected.len > 0:
|
if x.rejected.len > 0:
|
||||||
result["rejected"] = @@(x.rejected)
|
result["rejected"] = @@(x.rejected)
|
||||||
|
if x.currentBaseFee.isSome:
|
||||||
|
result["currentBaseFee"] = @@(x.currentBaseFee)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import
|
import
|
||||||
std/[json, strutils, times, tables, os, sets],
|
std/[json, strutils, times, tables, os, sets],
|
||||||
eth/[rlp, trie],
|
eth/[rlp, trie, eip1559],
|
||||||
stint, chronicles, stew/results,
|
stint, chronicles, stew/results,
|
||||||
"."/[config, types, helpers],
|
"."/[config, types, helpers],
|
||||||
../../nimbus/[vm_types, vm_state, transaction],
|
../../nimbus/[vm_types, vm_state, transaction],
|
||||||
@ -11,6 +11,7 @@ import
|
|||||||
../../nimbus/core/dao,
|
../../nimbus/core/dao,
|
||||||
../../nimbus/core/executor/[process_transaction, executor_helpers]
|
../../nimbus/core/executor/[process_transaction, executor_helpers]
|
||||||
|
|
||||||
|
import stew/byteutils
|
||||||
const
|
const
|
||||||
wrapExceptionEnabled* {.booldefine.} = true
|
wrapExceptionEnabled* {.booldefine.} = true
|
||||||
stdinSelector = "stdin"
|
stdinSelector = "stdin"
|
||||||
@ -56,7 +57,10 @@ proc dispatchOutput(ctx: var TransContext, conf: T8NConf, res: ExecOutput) =
|
|||||||
dis.dispatch(conf.outputBaseDir, conf.outputAlloc, "alloc", @@(res.alloc))
|
dis.dispatch(conf.outputBaseDir, conf.outputAlloc, "alloc", @@(res.alloc))
|
||||||
dis.dispatch(conf.outputBaseDir, conf.outputResult, "result", @@(res.result))
|
dis.dispatch(conf.outputBaseDir, conf.outputResult, "result", @@(res.result))
|
||||||
|
|
||||||
let body = @@(rlp.encode(ctx.txs))
|
let chainId = conf.stateChainId.ChainId
|
||||||
|
let txList = ctx.txList(chainId)
|
||||||
|
|
||||||
|
let body = @@(rlp.encode(txList))
|
||||||
dis.dispatch(conf.outputBaseDir, conf.outputBody, "body", body)
|
dis.dispatch(conf.outputBaseDir, conf.outputBody, "body", body)
|
||||||
|
|
||||||
if dis.stdout.len > 0:
|
if dis.stdout.len > 0:
|
||||||
@ -133,8 +137,10 @@ proc exec(ctx: var TransContext,
|
|||||||
stateReward: Option[UInt256],
|
stateReward: Option[UInt256],
|
||||||
header: BlockHeader): ExecOutput =
|
header: BlockHeader): ExecOutput =
|
||||||
|
|
||||||
|
let txList = ctx.parseTxs(vmState.com.chainId)
|
||||||
|
|
||||||
var
|
var
|
||||||
receipts = newSeqOfCap[TxReceipt](ctx.txs.len)
|
receipts = newSeqOfCap[TxReceipt](txList.len)
|
||||||
rejected = newSeq[RejectedTx]()
|
rejected = newSeq[RejectedTx]()
|
||||||
includedTx = newSeq[Transaction]()
|
includedTx = newSeq[Transaction]()
|
||||||
|
|
||||||
@ -143,10 +149,18 @@ proc exec(ctx: var TransContext,
|
|||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
db.applyDAOHardFork()
|
db.applyDAOHardFork()
|
||||||
|
|
||||||
vmState.receipts = newSeqOfCap[Receipt](ctx.txs.len)
|
vmState.receipts = newSeqOfCap[Receipt](txList.len)
|
||||||
vmState.cumulativeGasUsed = 0
|
vmState.cumulativeGasUsed = 0
|
||||||
|
|
||||||
for txIndex, tx in ctx.txs:
|
for txIndex, txRes in txList:
|
||||||
|
if txRes.isErr:
|
||||||
|
rejected.add RejectedTx(
|
||||||
|
index: txIndex,
|
||||||
|
error: txRes.error
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
let tx = txRes.get
|
||||||
var sender: EthAddress
|
var sender: EthAddress
|
||||||
if not tx.getSender(sender):
|
if not tx.getSender(sender):
|
||||||
rejected.add RejectedTx(
|
rejected.add RejectedTx(
|
||||||
@ -176,7 +190,13 @@ proc exec(ctx: var TransContext,
|
|||||||
)
|
)
|
||||||
includedTx.add tx
|
includedTx.add tx
|
||||||
|
|
||||||
|
# Add mining reward? (-1 means rewards are disabled)
|
||||||
if stateReward.isSome and stateReward.get >= 0:
|
if stateReward.isSome and stateReward.get >= 0:
|
||||||
|
# Add mining reward. The mining reward may be `0`, which only makes a difference in the cases
|
||||||
|
# where
|
||||||
|
# - the coinbase suicided, or
|
||||||
|
# - there are only 'bad' transactions, which aren't executed. In those cases,
|
||||||
|
# the coinbase gets no txfee, so isn't created, and thus needs to be touched
|
||||||
let blockReward = stateReward.get()
|
let blockReward = stateReward.get()
|
||||||
var mainReward = blockReward
|
var mainReward = blockReward
|
||||||
for uncle in ctx.env.ommers:
|
for uncle in ctx.env.ommers:
|
||||||
@ -216,7 +236,8 @@ proc exec(ctx: var TransContext,
|
|||||||
# geth using both vmContext.Difficulty and vmContext.Random
|
# geth using both vmContext.Difficulty and vmContext.Random
|
||||||
# therefore we cannot use vmState.difficulty
|
# therefore we cannot use vmState.difficulty
|
||||||
currentDifficulty: ctx.env.currentDifficulty,
|
currentDifficulty: ctx.env.currentDifficulty,
|
||||||
gasUsed : vmState.cumulativeGasUsed
|
gasUsed : vmState.cumulativeGasUsed,
|
||||||
|
currentBaseFee: ctx.env.currentBaseFee
|
||||||
)
|
)
|
||||||
|
|
||||||
template wrapException(body: untyped) =
|
template wrapException(body: untyped) =
|
||||||
@ -261,6 +282,20 @@ proc parseChainConfig(network: string): ChainConfig =
|
|||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise newError(ErrorConfig, e.msg)
|
raise newError(ErrorConfig, e.msg)
|
||||||
|
|
||||||
|
proc calcBaseFee(env: EnvStruct): UInt256 =
|
||||||
|
if env.parentGasUsed.isNone:
|
||||||
|
raise newError(ErrorConfig,
|
||||||
|
"'parentBaseFee' exists but missing 'parentGasUsed' in env section")
|
||||||
|
|
||||||
|
if env.parentGasLimit.isNone:
|
||||||
|
raise newError(ErrorConfig,
|
||||||
|
"'parentBaseFee' exists but missing 'parentGasLimit' in env section")
|
||||||
|
|
||||||
|
calcEip1599BaseFee(
|
||||||
|
env.parentGasLimit.get,
|
||||||
|
env.parentGasUsed.get,
|
||||||
|
env.parentBaseFee.get)
|
||||||
|
|
||||||
proc transitionAction*(ctx: var TransContext, conf: T8NConf) =
|
proc transitionAction*(ctx: var TransContext, conf: T8NConf) =
|
||||||
wrapException:
|
wrapException:
|
||||||
var tracerFlags = {
|
var tracerFlags = {
|
||||||
@ -291,7 +326,7 @@ proc transitionAction*(ctx: var TransContext, conf: T8NConf) =
|
|||||||
if conf.inputAlloc == stdinSelector or
|
if conf.inputAlloc == stdinSelector or
|
||||||
conf.inputEnv == stdinSelector or
|
conf.inputEnv == stdinSelector or
|
||||||
conf.inputTxs == stdinSelector:
|
conf.inputTxs == stdinSelector:
|
||||||
ctx.parseInputFromStdin(com.chainId)
|
ctx.parseInputFromStdin()
|
||||||
|
|
||||||
if conf.inputAlloc != stdinSelector and conf.inputAlloc.len > 0:
|
if conf.inputAlloc != stdinSelector and conf.inputAlloc.len > 0:
|
||||||
let n = json.parseFile(conf.inputAlloc)
|
let n = json.parseFile(conf.inputAlloc)
|
||||||
@ -307,7 +342,7 @@ proc transitionAction*(ctx: var TransContext, conf: T8NConf) =
|
|||||||
ctx.parseTxsRlp(data.strip(chars={'"'}))
|
ctx.parseTxsRlp(data.strip(chars={'"'}))
|
||||||
else:
|
else:
|
||||||
let n = json.parseFile(conf.inputTxs)
|
let n = json.parseFile(conf.inputTxs)
|
||||||
ctx.parseTxs(n, com.chainId)
|
ctx.parseTxs(n)
|
||||||
|
|
||||||
let uncleHash = if ctx.env.parentUncleHash == Hash256():
|
let uncleHash = if ctx.env.parentUncleHash == Hash256():
|
||||||
EMPTY_UNCLE_HASH
|
EMPTY_UNCLE_HASH
|
||||||
@ -324,7 +359,12 @@ proc transitionAction*(ctx: var TransContext, conf: T8NConf) =
|
|||||||
|
|
||||||
# Sanity check, to not `panic` in state_transition
|
# Sanity check, to not `panic` in state_transition
|
||||||
if com.isLondon(ctx.env.currentNumber):
|
if com.isLondon(ctx.env.currentNumber):
|
||||||
if ctx.env.currentBaseFee.isNone:
|
if ctx.env.currentBaseFee.isSome:
|
||||||
|
# Already set, currentBaseFee has precedent over parentBaseFee.
|
||||||
|
discard
|
||||||
|
elif ctx.env.parentBaseFee.isSome:
|
||||||
|
ctx.env.currentBaseFee = some(calcBaseFee(ctx.env))
|
||||||
|
else:
|
||||||
raise newError(ErrorConfig, "EIP-1559 config but missing 'currentBaseFee' in env section")
|
raise newError(ErrorConfig, "EIP-1559 config but missing 'currentBaseFee' in env section")
|
||||||
|
|
||||||
if com.forkGTE(MergeFork):
|
if com.forkGTE(MergeFork):
|
||||||
|
96
tools/t8n/txpriv.nim
Normal file
96
tools/t8n/txpriv.nim
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import
|
||||||
|
eth/common
|
||||||
|
|
||||||
|
from stew/objects
|
||||||
|
import checkedEnumAssign
|
||||||
|
|
||||||
|
# these procs are duplicates of nim-eth/eth_types_rlp.nim
|
||||||
|
# both `readTxLegacy` and `readTxTyped` are exported here
|
||||||
|
|
||||||
|
template read[T](rlp: var Rlp, val: var T)=
|
||||||
|
val = rlp.read(type val)
|
||||||
|
|
||||||
|
proc read[T](rlp: var Rlp, val: var Option[T])=
|
||||||
|
if rlp.blobLen != 0:
|
||||||
|
val = some(rlp.read(T))
|
||||||
|
else:
|
||||||
|
rlp.skipElem
|
||||||
|
|
||||||
|
proc readTxLegacy*(rlp: var Rlp, tx: var Transaction)=
|
||||||
|
tx.txType = TxLegacy
|
||||||
|
rlp.tryEnterList()
|
||||||
|
rlp.read(tx.nonce)
|
||||||
|
rlp.read(tx.gasPrice)
|
||||||
|
rlp.read(tx.gasLimit)
|
||||||
|
rlp.read(tx.to)
|
||||||
|
rlp.read(tx.value)
|
||||||
|
rlp.read(tx.payload)
|
||||||
|
rlp.read(tx.V)
|
||||||
|
rlp.read(tx.R)
|
||||||
|
rlp.read(tx.S)
|
||||||
|
|
||||||
|
proc readTxEip2930(rlp: var Rlp, tx: var Transaction)=
|
||||||
|
tx.txType = TxEip2930
|
||||||
|
rlp.tryEnterList()
|
||||||
|
tx.chainId = rlp.read(uint64).ChainId
|
||||||
|
rlp.read(tx.nonce)
|
||||||
|
rlp.read(tx.gasPrice)
|
||||||
|
rlp.read(tx.gasLimit)
|
||||||
|
rlp.read(tx.to)
|
||||||
|
rlp.read(tx.value)
|
||||||
|
rlp.read(tx.payload)
|
||||||
|
rlp.read(tx.accessList)
|
||||||
|
rlp.read(tx.V)
|
||||||
|
rlp.read(tx.R)
|
||||||
|
rlp.read(tx.S)
|
||||||
|
|
||||||
|
proc readTxEip1559(rlp: var Rlp, tx: var Transaction)=
|
||||||
|
tx.txType = TxEip1559
|
||||||
|
rlp.tryEnterList()
|
||||||
|
tx.chainId = rlp.read(uint64).ChainId
|
||||||
|
rlp.read(tx.nonce)
|
||||||
|
rlp.read(tx.maxPriorityFee)
|
||||||
|
rlp.read(tx.maxFee)
|
||||||
|
rlp.read(tx.gasLimit)
|
||||||
|
rlp.read(tx.to)
|
||||||
|
rlp.read(tx.value)
|
||||||
|
rlp.read(tx.payload)
|
||||||
|
rlp.read(tx.accessList)
|
||||||
|
rlp.read(tx.V)
|
||||||
|
rlp.read(tx.R)
|
||||||
|
rlp.read(tx.S)
|
||||||
|
|
||||||
|
proc readTxTyped*(rlp: var Rlp, tx: var Transaction) {.inline.} =
|
||||||
|
# EIP-2718: We MUST decode the first byte as a byte, not `rlp.read(int)`.
|
||||||
|
# If decoded with `rlp.read(int)`, bad transaction data (from the network)
|
||||||
|
# or even just incorrectly framed data for other reasons fails with
|
||||||
|
# any of these misleading error messages:
|
||||||
|
# - "Message too large to fit in memory"
|
||||||
|
# - "Number encoded with a leading zero"
|
||||||
|
# - "Read past the end of the RLP stream"
|
||||||
|
# - "Small number encoded in a non-canonical way"
|
||||||
|
# - "Attempt to read an Int value past the RLP end"
|
||||||
|
# - "The RLP contains a larger than expected Int value"
|
||||||
|
if not rlp.isSingleByte:
|
||||||
|
if not rlp.hasData:
|
||||||
|
raise newException(MalformedRlpError,
|
||||||
|
"Transaction expected but source RLP is empty")
|
||||||
|
raise newException(MalformedRlpError,
|
||||||
|
"TypedTransaction type byte is out of range, must be 0x00 to 0x7f")
|
||||||
|
let txType = rlp.getByteValue
|
||||||
|
rlp.position += 1
|
||||||
|
|
||||||
|
var txVal: TxType
|
||||||
|
if checkedEnumAssign(txVal, txType):
|
||||||
|
case txVal:
|
||||||
|
of TxEip2930:
|
||||||
|
rlp.readTxEip2930(tx)
|
||||||
|
return
|
||||||
|
of TxEip1559:
|
||||||
|
rlp.readTxEip1559(tx)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
|
raise newException(UnsupportedRlpError,
|
||||||
|
"TypedTransaction type must be 1 or 2 in this version, got " & $txType)
|
@ -9,7 +9,7 @@
|
|||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[tables],
|
std/[tables, json],
|
||||||
eth/common,
|
eth/common,
|
||||||
../../nimbus/common/chain_config,
|
../../nimbus/common/chain_config,
|
||||||
../common/types
|
../common/types
|
||||||
@ -40,10 +40,24 @@ type
|
|||||||
ommers*: seq[Ommer]
|
ommers*: seq[Ommer]
|
||||||
currentBaseFee*: Option[UInt256]
|
currentBaseFee*: Option[UInt256]
|
||||||
parentUncleHash*: Hash256
|
parentUncleHash*: Hash256
|
||||||
|
parentBaseFee*: Option[UInt256]
|
||||||
|
parentGasUsed*: Option[GasInt]
|
||||||
|
parentGasLimit*: Option[GasInt]
|
||||||
|
|
||||||
|
TxsType* = enum
|
||||||
|
TxsNone
|
||||||
|
TxsRlp
|
||||||
|
TxsJson
|
||||||
|
|
||||||
|
TxsList* = object
|
||||||
|
case txsType*: TxsType
|
||||||
|
of TxsRlp: r*: Rlp
|
||||||
|
of TxsJson: n*: JsonNode
|
||||||
|
else: discard
|
||||||
|
|
||||||
TransContext* = object
|
TransContext* = object
|
||||||
alloc*: GenesisAlloc
|
alloc*: GenesisAlloc
|
||||||
txs*: seq[Transaction]
|
txs*: TxsList
|
||||||
env*: EnvStruct
|
env*: EnvStruct
|
||||||
|
|
||||||
RejectedTx* = object
|
RejectedTx* = object
|
||||||
@ -75,6 +89,7 @@ type
|
|||||||
rejected*: seq[RejectedTx]
|
rejected*: seq[RejectedTx]
|
||||||
currentDifficulty*: Option[DifficultyInt]
|
currentDifficulty*: Option[DifficultyInt]
|
||||||
gasUsed*: GasInt
|
gasUsed*: GasInt
|
||||||
|
currentBaseFee*: Option[UInt256]
|
||||||
|
|
||||||
const
|
const
|
||||||
ErrorEVM* = 2.T8NExitCode
|
ErrorEVM* = 2.T8NExitCode
|
||||||
|
Loading…
x
Reference in New Issue
Block a user