graphql: add Shanghai and Cancun fields
This commit is contained in:
parent
31cff910b1
commit
81b7a8c682
|
@ -91,7 +91,11 @@ proc main() =
|
|||
|
||||
var stat: SimStat
|
||||
let start = getTime()
|
||||
for fileName {.inject.} in walkDirRec(
|
||||
|
||||
#let fileName = caseFolder & "/37_eth_sendRawTransaction_nonceTooLow.json"
|
||||
#block:
|
||||
|
||||
for fileName in walkDirRec(
|
||||
caseFolder, yieldFilter = {pcFile,pcLinkToFile}):
|
||||
if not fileName.endsWith(".json"):
|
||||
continue
|
||||
|
@ -101,6 +105,9 @@ proc main() =
|
|||
let status = ctx.processNode(node, fileName)
|
||||
stat.inc(name, status)
|
||||
|
||||
# simulate the real simulator
|
||||
txPool.disposeAll()
|
||||
|
||||
let elpd = getTime() - start
|
||||
print(stat, elpd, "graphql")
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,4 +1,20 @@
|
|||
{
|
||||
"config": {
|
||||
"chainId": 1,
|
||||
"homesteadBlock": 33,
|
||||
"eip150Block": 33,
|
||||
"eip155Block": 33,
|
||||
"eip158Block": 33,
|
||||
"byzantiumBlock": 33,
|
||||
"constantinopleBlock": 33,
|
||||
"petersburgBlock": 33,
|
||||
"istanbulBlock": 33,
|
||||
"muirGlacierBlock": 33,
|
||||
"berlinBlock": 33,
|
||||
"londonBlock": 33,
|
||||
"terminalTotalDifficulty": 4357120,
|
||||
"shanghaiTime": 1444660030
|
||||
},
|
||||
"genesis": {
|
||||
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
|
|
|
@ -166,6 +166,7 @@ proc readValue(reader: var JsonReader, value: var BlockNonce)
|
|||
except ValueError as ex:
|
||||
reader.raiseUnexpectedValue(ex.msg)
|
||||
|
||||
# genesis timestamp is in hex
|
||||
proc readValue(reader: var JsonReader, value: var EthTime)
|
||||
{.gcsafe, raises: [SerializationError, IOError].} =
|
||||
try:
|
||||
|
@ -173,6 +174,21 @@ proc readValue(reader: var JsonReader, value: var EthTime)
|
|||
except ValueError as ex:
|
||||
reader.raiseUnexpectedValue(ex.msg)
|
||||
|
||||
# but shanghaiTime and cancunTime in config is in int literal
|
||||
proc readValue(reader: var JsonReader, value: var Option[EthTime])
|
||||
{.gcsafe, raises: [SerializationError, IOError].} =
|
||||
let tok = reader.lexer.lazyTok
|
||||
if tok == tkNull:
|
||||
reset value
|
||||
reader.lexer.next()
|
||||
else:
|
||||
# both readValue(GasInt/AccountNonce) will be called if
|
||||
# we use readValue(int64/uint64)
|
||||
let tok {.used.} = reader.lexer.tok # resove lazy token
|
||||
let val = reader.lexer.absIntVal.int64
|
||||
value = some val.fromUnix
|
||||
reader.lexer.next()
|
||||
|
||||
proc readValue(reader: var JsonReader, value: var seq[byte])
|
||||
{.gcsafe, raises: [SerializationError, IOError].} =
|
||||
try:
|
||||
|
|
|
@ -804,6 +804,14 @@ iterator okPairs*(xp: TxPoolRef): (Hash256, TxItemRef) =
|
|||
proc numTxs*(xp: TxPoolRef): int =
|
||||
xp.txDB.byItemID.len
|
||||
|
||||
proc disposeAll*(xp: TxpoolRef) {.gcsafe,raises: [CatchableError].} =
|
||||
let numTx = xp.numTxs
|
||||
var list = newSeqOfCap[TxItemRef](numTx)
|
||||
for x in nextPairs(xp.txDB.byItemID):
|
||||
list.add x.data
|
||||
for x in list:
|
||||
xp.disposeItems(x)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions, local/remote accounts
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -227,10 +227,12 @@ proc getTransactionCount*(chain: ChainDBRef, txRoot: Hash256): int =
|
|||
var txCount = 0
|
||||
while true:
|
||||
let txKey = rlp.encode(txCount)
|
||||
if txKey notin trie:
|
||||
break
|
||||
inc txCount
|
||||
txCount
|
||||
if txKey in trie:
|
||||
inc txCount
|
||||
else:
|
||||
return txCount
|
||||
|
||||
doAssert(false, "unreachable")
|
||||
|
||||
proc getUnclesCount*(db: ChainDBRef, ommersHash: Hash256): int =
|
||||
if ommersHash != EMPTY_UNCLE_HASH:
|
||||
|
@ -263,6 +265,10 @@ iterator getWithdrawalsData*(db: ChainDBRef, withdrawalsRoot: Hash256): seq[byte
|
|||
break
|
||||
inc idx
|
||||
|
||||
proc getWithdrawals*(db: ChainDBRef, withdrawalsRoot: Hash256): seq[Withdrawal] =
|
||||
for encodedWd in db.getWithdrawalsData(withdrawalsRoot):
|
||||
result.add(rlp.decode(encodedWd, Withdrawal))
|
||||
|
||||
proc getBlockBody*(db: ChainDBRef, header: BlockHeader, output: var BlockBody): bool =
|
||||
result = true
|
||||
output.transactions = @[]
|
||||
|
@ -278,10 +284,7 @@ proc getBlockBody*(db: ChainDBRef, header: BlockHeader, output: var BlockBody):
|
|||
result = false
|
||||
|
||||
if header.withdrawalsRoot.isSome:
|
||||
var withdrawals: seq[Withdrawal]
|
||||
for encodedWd in db.getWithdrawalsData(header.withdrawalsRoot.get):
|
||||
withdrawals.add(rlp.decode(encodedWd, Withdrawal))
|
||||
output.withdrawals = some(withdrawals)
|
||||
output.withdrawals = some(db.getWithdrawals(header.withdrawalsRoot.get))
|
||||
|
||||
proc getBlockBody*(db: ChainDBRef, blockHash: Hash256, output: var BlockBody): bool =
|
||||
var header: BlockHeader
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
import
|
||||
std/[strutils, times],
|
||||
stew/[results, byteutils], stint,
|
||||
eth/[rlp], chronos,
|
||||
eth/common/eth_types_rlp, chronos,
|
||||
stew/shims/net,
|
||||
graphql, graphql/graphql as context,
|
||||
graphql/common/types, graphql/httpserver,
|
||||
|
@ -19,7 +19,7 @@ import
|
|||
".."/[transaction, vm_state, config, constants],
|
||||
../common/common,
|
||||
../transaction/call_evm,
|
||||
../core/tx_pool,
|
||||
../core/[tx_pool, tx_pool/tx_item],
|
||||
../utils/utils
|
||||
|
||||
from eth/p2p import EthereumNode
|
||||
|
@ -37,6 +37,7 @@ type
|
|||
ethQuery = "Query"
|
||||
ethMutation = "Mutation"
|
||||
ethAccessTuple = "AccessTuple"
|
||||
ethWithdrawal = "Withdrawal"
|
||||
|
||||
HeaderNode = ref object of Node
|
||||
header: BlockHeader
|
||||
|
@ -62,6 +63,9 @@ type
|
|||
AclNode = ref object of Node
|
||||
acl: AccessPair
|
||||
|
||||
WdNode = ref object of Node
|
||||
wd: Withdrawal
|
||||
|
||||
GraphqlContextRef = ref GraphqlContextObj
|
||||
GraphqlContextObj = object of Graphql
|
||||
ids: array[EthTypes, Name]
|
||||
|
@ -79,7 +83,12 @@ proc toHash(n: Node): Hash256 =
|
|||
result.data = hexToByteArray[32](n.stringVal)
|
||||
|
||||
proc toBlockNumber(n: Node): BlockNumber =
|
||||
result = parse(n.intVal, UInt256, radix = 10)
|
||||
if n.kind == nkInt:
|
||||
result = parse(n.intVal, UInt256, radix = 10)
|
||||
elif n.kind == nkString:
|
||||
result = parse(n.stringVal, UInt256, radix = 16)
|
||||
else:
|
||||
doAssert(false, "unknown node type: " & $n.kind)
|
||||
|
||||
proc headerNode(ctx: GraphqlContextRef, header: BlockHeader): Node =
|
||||
HeaderNode(
|
||||
|
@ -128,6 +137,14 @@ proc aclNode(ctx: GraphqlContextRef, accessPair: AccessPair): Node =
|
|||
acl: accessPair
|
||||
)
|
||||
|
||||
proc wdNode(ctx: GraphqlContextRef, wd: Withdrawal): Node =
|
||||
WdNode(
|
||||
kind: nkMap,
|
||||
typeName: ctx.ids[ethWithdrawal],
|
||||
pos: Pos(),
|
||||
wd: wd
|
||||
)
|
||||
|
||||
proc getStateDB(com: CommonRef, header: BlockHeader): ReadOnlyStateDB =
|
||||
## Retrieves the account db from canonical head
|
||||
## we don't use accounst_cache here because it's read only operations
|
||||
|
@ -190,6 +207,10 @@ proc bigIntNode(x: uint64 | int64): RespResult =
|
|||
# stdlib toHex is not suitable for hive
|
||||
const
|
||||
HexChars = "0123456789abcdef"
|
||||
|
||||
if x == 0:
|
||||
return ok(Node(kind: nkString, stringVal: "0x0", pos: Pos()))
|
||||
|
||||
var
|
||||
n = cast[uint64](x)
|
||||
r: array[2*sizeof(uint64), char]
|
||||
|
@ -278,6 +299,19 @@ proc getTxs(ctx: GraphqlContextRef, header: BlockHeader): RespResult =
|
|||
except CatchableError as e:
|
||||
err("can't get transactions: " & e.msg)
|
||||
|
||||
proc getWithdrawals(ctx: GraphqlContextRef, header: BlockHeader): RespResult =
|
||||
try:
|
||||
if header.withdrawalsRoot.isSome:
|
||||
let wds = getWithdrawals(ctx.chainDB, header.withdrawalsRoot.get)
|
||||
var list = respList()
|
||||
for wd in wds:
|
||||
list.add wdNode(ctx, wd)
|
||||
ok(list)
|
||||
else:
|
||||
ok(respNull())
|
||||
except CatchableError as e:
|
||||
err("can't get transactions: " & e.msg)
|
||||
|
||||
proc getTxAt(ctx: GraphqlContextRef, header: BlockHeader, index: int): RespResult =
|
||||
try:
|
||||
var tx: Transaction
|
||||
|
@ -323,9 +357,25 @@ proc accountNode(ctx: GraphqlContextRef, header: BlockHeader, address: EthAddres
|
|||
except RlpError as ex:
|
||||
err(ex.msg)
|
||||
|
||||
func hexCharToInt(c: char): uint64 =
|
||||
case c
|
||||
of 'a'..'f': return c.uint64 - 'a'.uint64 + 10'u64
|
||||
of 'A'..'F': return c.uint64 - 'A'.uint64 + 10'u64
|
||||
of '0'..'9': return c.uint64 - '0'.uint64
|
||||
else: doAssert(false, "invalid hex digit: " & $c)
|
||||
|
||||
proc parseU64(node: Node): uint64 =
|
||||
for c in node.intVal:
|
||||
result = result * 10 + uint64(c.int - '0'.int)
|
||||
if node.kind == nkString:
|
||||
if node.stringVal.len > 2 and node.stringVal[1] == 'x':
|
||||
for i in 2..<node.stringVal.len:
|
||||
let c = node.stringVal[i]
|
||||
result = result * 16 + hexCharToInt(c)
|
||||
else:
|
||||
for c in node.stringVal:
|
||||
result = result * 10 + (c.uint64 - '0'.uint64)
|
||||
else:
|
||||
for c in node.intVal:
|
||||
result = result * 10 + (c.uint64 - '0'.uint64)
|
||||
|
||||
{.pragma: apiRaises, raises: [].}
|
||||
|
||||
|
@ -462,17 +512,17 @@ proc scalarLong(ctx: GraphqlRef, typeNode, node: Node): NodeResult {.cdecl, gcsa
|
|||
let val = parse(node.stringVal, UInt256, radix = 16)
|
||||
if val > maxU64:
|
||||
return err("long value overflow")
|
||||
ok(Node(kind: nkInt, pos: node.pos, intVal: $val))
|
||||
ok(node)
|
||||
else:
|
||||
let val = parse(node.stringVal, UInt256, radix = 10)
|
||||
if val > maxU64:
|
||||
return err("long value overflow")
|
||||
ok(Node(kind: nkInt, pos: node.pos, intVal: node.stringVal))
|
||||
ok(Node(kind: nkString, pos: node.pos, stringVal: "0x" & val.toHex))
|
||||
of nkInt:
|
||||
let val = parse(node.intVal, UInt256, radix = 10)
|
||||
if val > maxU64:
|
||||
return err("long value overflow")
|
||||
ok(node)
|
||||
ok(Node(kind: nkString, pos: node.pos, stringVal: "0x" & val.toHex))
|
||||
else:
|
||||
err("expect int, but got '$1'" % [$node.kind])
|
||||
except CatchableError as e:
|
||||
|
@ -583,25 +633,35 @@ proc txIndex(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.}
|
|||
ok(resp(tx.index))
|
||||
|
||||
proc txFrom(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
# TODO: with block param
|
||||
let ctx = GraphqlContextRef(ud)
|
||||
let tx = TxNode(parent)
|
||||
|
||||
let blockNumber = if params[0].val.kind != nkEmpty:
|
||||
parseU64(params[0].val).toBlockNumber
|
||||
else:
|
||||
tx.blockNumber
|
||||
|
||||
var sender: EthAddress
|
||||
if not getSender(tx.tx, sender):
|
||||
return ok(respNull())
|
||||
let hres = ctx.getBlockByNumber(tx.blockNumber)
|
||||
let hres = ctx.getBlockByNumber(blockNumber)
|
||||
if hres.isErr:
|
||||
return hres
|
||||
let h = HeaderNode(hres.get())
|
||||
ctx.accountNode(h.header, sender)
|
||||
|
||||
proc txTo(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
# TODO: with block param
|
||||
let ctx = GraphqlContextRef(ud)
|
||||
let tx = TxNode(parent)
|
||||
|
||||
let blockNumber = if params[0].val.kind != nkEmpty:
|
||||
parseU64(params[0].val).toBlockNumber
|
||||
else:
|
||||
tx.blockNumber
|
||||
|
||||
if tx.tx.contractCreation:
|
||||
return ok(respNull())
|
||||
let hres = ctx.getBlockByNumber(tx.blockNumber)
|
||||
let hres = ctx.getBlockByNumber(blockNumber)
|
||||
if hres.isErr:
|
||||
return hres
|
||||
let h = HeaderNode(hres.get())
|
||||
|
@ -741,6 +801,35 @@ proc txAccessList(ud: RootRef, params: Args, parent: Node): RespResult {.apiPrag
|
|||
list.add aclNode(ctx, x)
|
||||
ok(list)
|
||||
|
||||
proc txMaxFeePerBlobGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let ctx = GraphqlContextRef(ud)
|
||||
let tx = TxNode(parent)
|
||||
if tx.tx.txType < TxEIP4844:
|
||||
ok(respNull())
|
||||
else:
|
||||
longNode(tx.tx.maxFeePerDataGas)
|
||||
|
||||
proc txVersionedHashes(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let ctx = GraphqlContextRef(ud)
|
||||
let tx = TxNode(parent)
|
||||
if tx.tx.txType < TxEIP4844:
|
||||
ok(respNull())
|
||||
else:
|
||||
var list = respList()
|
||||
for hs in tx.tx.versionedHashes:
|
||||
list.add resp("0x" & hs.data.toHex)
|
||||
ok(list)
|
||||
|
||||
proc txRaw(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let tx = TxNode(parent)
|
||||
let txBytes = rlp.encode(tx.tx)
|
||||
resp(txBytes)
|
||||
|
||||
proc txRawReceipt(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let tx = TxNode(parent)
|
||||
let recBytes = rlp.encode(tx.receipt)
|
||||
resp(recBytes)
|
||||
|
||||
const txProcs = {
|
||||
"from": txFrom,
|
||||
"hash": txHash,
|
||||
|
@ -765,7 +854,11 @@ const txProcs = {
|
|||
"maxFeePerGas": txMaxFeePerGas,
|
||||
"maxPriorityFeePerGas": txMaxPriorityFeePerGas,
|
||||
"effectiveGasPrice": txEffectiveGasPrice,
|
||||
"chainID": txChainId
|
||||
"chainID": txChainId,
|
||||
"maxFeePerBlobGas": txmaxFeePerBlobGas,
|
||||
"versionedHashes": txVersionedHashes,
|
||||
"raw": txRaw,
|
||||
"rawReceipt": txRawReceipt
|
||||
}
|
||||
|
||||
proc aclAddress(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
|
@ -787,6 +880,29 @@ const aclProcs = {
|
|||
"storageKeys": aclStorageKeys
|
||||
}
|
||||
|
||||
proc wdIndex(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let w = WdNode(parent)
|
||||
longNode(w.wd.index)
|
||||
|
||||
proc wdValidator(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let w = WdNode(parent)
|
||||
longNode(w.wd.validatorIndex)
|
||||
|
||||
proc wdAddress(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let w = WdNode(parent)
|
||||
resp(w.wd.address)
|
||||
|
||||
proc wdAmount(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let w = WdNode(parent)
|
||||
longNode(w.wd.amount)
|
||||
|
||||
const wdProcs = {
|
||||
"index": wdIndex,
|
||||
"validator": wdValidator,
|
||||
"address": wdAddress,
|
||||
"amount": wdAmount
|
||||
}
|
||||
|
||||
proc blockNumberImpl(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let ctx = GraphqlContextRef(ud)
|
||||
let h = HeaderNode(parent)
|
||||
|
@ -1012,6 +1128,32 @@ proc blockBaseFeePerGas(ud: RootRef, params: Args, parent: Node): RespResult {.a
|
|||
else:
|
||||
ok(respNull())
|
||||
|
||||
proc blockWithdrawalsRoot(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let h = HeaderNode(parent)
|
||||
if h.header.withdrawalsRoot.isSome:
|
||||
resp(h.header.withdrawalsRoot.get)
|
||||
else:
|
||||
ok(respNull())
|
||||
|
||||
proc blockWithdrawals(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let ctx = GraphqlContextRef(ud)
|
||||
let h = HeaderNode(parent)
|
||||
getWithdrawals(ctx, h.header)
|
||||
|
||||
proc blockBlobGasUsed(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let h = HeaderNode(parent)
|
||||
if h.header.dataGasUsed.isSome:
|
||||
longNode(h.header.dataGasUsed.get)
|
||||
else:
|
||||
ok(respNull())
|
||||
|
||||
proc blockexcessBlobGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
let h = HeaderNode(parent)
|
||||
if h.header.excessDataGas.isSome:
|
||||
longNode(h.header.excessDataGas.get)
|
||||
else:
|
||||
ok(respNull())
|
||||
|
||||
const blockProcs = {
|
||||
"parent": blockParent,
|
||||
"number": blockNumberImpl,
|
||||
|
@ -1040,7 +1182,11 @@ const blockProcs = {
|
|||
"account": blockAccount,
|
||||
"call": blockCall,
|
||||
"estimateGas": blockEstimateGas,
|
||||
"baseFeePerGas": blockBaseFeePerGas
|
||||
"baseFeePerGas": blockBaseFeePerGas,
|
||||
"withdrawalsRoot": blockWithdrawalsRoot,
|
||||
"withdrawals": blockWithdrawals,
|
||||
"blobGasUsed": blockBlobGasUsed,
|
||||
"excessBlobGas": blockExcessBlobGas
|
||||
}
|
||||
|
||||
proc callResultData(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
|
@ -1151,6 +1297,12 @@ proc queryBlock(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma
|
|||
err("only one param allowed, number or hash, not both")
|
||||
elif number.kind == nkInt:
|
||||
getBlockByNumber(ctx, number)
|
||||
elif number.kind == nkString:
|
||||
try:
|
||||
let blockNumber = toBlockNumber(number)
|
||||
getBlockByNumber(ctx, blockNumber)
|
||||
except ValueError as ex:
|
||||
err(ex.msg)
|
||||
elif hash.kind == nkString:
|
||||
getBlockByHash(ctx, hash)
|
||||
else:
|
||||
|
@ -1241,16 +1393,26 @@ const queryProcs = {
|
|||
"chainID": queryChainId
|
||||
}
|
||||
|
||||
proc inPoolAndOk(ctx: GraphqlContextRef, txHash: Hash256): bool =
|
||||
let res = ctx.txPool.getItem(txHash)
|
||||
if res.isErr: return false
|
||||
res.get().reject == txInfoOk
|
||||
|
||||
proc sendRawTransaction(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||
# TODO: add tx validation and tx processing
|
||||
# probably goes to tx pool
|
||||
# if tx validation failed, the result will be null
|
||||
let ctx = GraphqlContextRef(ud)
|
||||
try:
|
||||
let data = hexToSeqByte(params[0].val.stringVal)
|
||||
let tx = decodeTx(data) # we want to know if it is a valid tx blob
|
||||
let txHash = rlpHash(tx) # beware EIP-4844
|
||||
resp(txHash)
|
||||
|
||||
ctx.txPool.add(tx)
|
||||
|
||||
if ctx.inPoolAndOk(txHash):
|
||||
return resp(txHash)
|
||||
else:
|
||||
return err("transaction rejected by txpool")
|
||||
|
||||
except CatchableError as em:
|
||||
return err("failed to process raw transaction: " & em.msg)
|
||||
|
||||
|
@ -1315,6 +1477,7 @@ proc initEthApi(ctx: GraphqlContextRef) =
|
|||
ctx.addResolvers(ctx, ctx.ids[ethQuery ], queryProcs)
|
||||
ctx.addResolvers(ctx, ctx.ids[ethMutation ], mutationProcs)
|
||||
ctx.addResolvers(ctx, ctx.ids[ethAccessTuple], aclProcs)
|
||||
ctx.addResolvers(ctx, ctx.ids[ethWithdrawal ], wdProcs)
|
||||
|
||||
var qc = newQC(ctx)
|
||||
ctx.addInstrument(qc)
|
||||
|
|
|
@ -5,7 +5,7 @@ scalar Bytes32
|
|||
scalar Address
|
||||
|
||||
# Bytes is an arbitrary length binary string, represented as 0x-prefixed hexadecimal.
|
||||
# An empty byte string is represented as '0x'. Byte strings must have an even number of hexadecimal nybbles.
|
||||
# An empty byte string is represented as '0x'. Byte strings must have an even number of hexadecimal nibbles.
|
||||
scalar Bytes
|
||||
|
||||
# BigInt is a large integer. Input is accepted as either a JSON number or as a string.
|
||||
|
@ -13,7 +13,9 @@ scalar Bytes
|
|||
# 0x-prefixed hexadecimal.
|
||||
scalar BigInt
|
||||
|
||||
# Long is a 64 bit unsigned integer.
|
||||
# Long is a 64 bit unsigned integer. Input is accepted as either a JSON number or as a string.
|
||||
# Strings may be either decimal or 0x-prefixed hexadecimal. Output values are all
|
||||
# 0x-prefixed hexadecimal.
|
||||
scalar Long
|
||||
|
||||
schema {
|
||||
|
@ -46,7 +48,7 @@ type Account {
|
|||
# Log is an Ethereum event log.
|
||||
type Log {
|
||||
# Index is the index of this log in the block.
|
||||
index: Int!
|
||||
index: Long!
|
||||
|
||||
# Account is the account which generated this log - this will always
|
||||
# be a contract account.
|
||||
|
@ -64,13 +66,28 @@ type Log {
|
|||
|
||||
# EIP-2718 Access List
|
||||
type AccessTuple {
|
||||
# access list address
|
||||
# access list address.
|
||||
address: Address!
|
||||
|
||||
# access list storage keys, null if not present
|
||||
# access list storage keys, null if not present.
|
||||
storageKeys: [Bytes32!]
|
||||
}
|
||||
|
||||
# EIP-4895
|
||||
type Withdrawal {
|
||||
# Index is a monotonically increasing identifier issued by consensus layer.
|
||||
index: Long!
|
||||
|
||||
# Validator is index of the validator associated with withdrawal.
|
||||
validator: Long!
|
||||
|
||||
# Recipient address of the withdrawn amount.
|
||||
address: Address!
|
||||
|
||||
# Amount is the withdrawal value in Gwei.
|
||||
amount: Long!
|
||||
}
|
||||
|
||||
# Transaction is an Ethereum transaction.
|
||||
type Transaction {
|
||||
# Hash is the hash of this transaction.
|
||||
|
@ -81,7 +98,7 @@ type Transaction {
|
|||
|
||||
# Index is the index of this transaction in the parent block. This will
|
||||
# be null if the transaction has not yet been mined.
|
||||
index: Int
|
||||
index: Long
|
||||
|
||||
# From is the account that sent this transaction - this will always be
|
||||
# an externally owned account.
|
||||
|
@ -157,14 +174,31 @@ type Transaction {
|
|||
v: BigInt!
|
||||
|
||||
# EIP 2718: envelope transaction support
|
||||
type: Int
|
||||
type: Long
|
||||
|
||||
# EIP 2930: optional access list, null if not present
|
||||
accessList: [AccessTuple!]
|
||||
|
||||
# EIP-4844: blob gas a user willing to pay
|
||||
maxFeePerBlobGas: Long
|
||||
|
||||
# EIP-4844: represents a list of hash outputs from kzg_to_versioned_hash
|
||||
versionedHashes: [Bytes32!]
|
||||
|
||||
#--------------------------Extensions-------------------------------
|
||||
|
||||
# If type == 0, chainID returns null.
|
||||
# If type > 0, chainID returns replay protection chainID
|
||||
chainID: Long
|
||||
|
||||
# Raw is the canonical encoding of the transaction.
|
||||
# For legacy transactions, it returns the RLP encoding.
|
||||
# For EIP-2718 typed transactions, it returns the type and payload.
|
||||
raw: Bytes!
|
||||
|
||||
# RawReceipt is the canonical encoding of the receipt. For post EIP-2718 typed transactions
|
||||
# this is equivalent to TxType || ReceiptEncoding.
|
||||
rawReceipt: Bytes!
|
||||
}
|
||||
|
||||
# BlockFilterCriteria encapsulates log filter criteria for a filter applied
|
||||
|
@ -207,7 +241,7 @@ type Block {
|
|||
|
||||
# TransactionCount is the number of transactions in this block. if
|
||||
# transactions are not available for this block, this field will be null.
|
||||
transactionCount: Int
|
||||
transactionCount: Long
|
||||
|
||||
# StateRoot is the keccak256 hash of the state trie after this block was processed.
|
||||
stateRoot: Bytes32!
|
||||
|
@ -249,7 +283,7 @@ type Block {
|
|||
|
||||
# OmmerCount is the number of ommers (AKA uncles) associated with this
|
||||
# block. If ommers are unavailable, this field will be null.
|
||||
ommerCount: Int
|
||||
ommerCount: Long
|
||||
|
||||
# Ommers is a list of ommer (AKA uncle) blocks associated with this block.
|
||||
# If ommers are unavailable, this field will be null. Depending on your
|
||||
|
@ -286,6 +320,32 @@ type Block {
|
|||
# EstimateGas estimates the amount of gas that will be required for
|
||||
# successful execution of a transaction at the current block's state.
|
||||
estimateGas(data: CallData!): Long!
|
||||
|
||||
# WithdrawalsRoot is the withdrawals trie root in this block.
|
||||
# If withdrawals are unavailable for this block, this field will be null.
|
||||
withdrawalsRoot: Bytes32
|
||||
|
||||
# Withdrawals is a list of withdrawals associated with this block. If
|
||||
# withdrawals are unavailable for this block, this field will be null.
|
||||
withdrawals: [Withdrawal!]
|
||||
|
||||
# EIP-4844: is the total amount of blob gas consumed by the transactions
|
||||
# within the block.
|
||||
blobGasUsed: Long
|
||||
|
||||
# EIP-4844: is a running total of blob gas consumed in excess of the target,
|
||||
# prior to the block. Blocks with above-target blob gas consumption increase
|
||||
# this value, blocks with below-target blob gas consumption decrease it
|
||||
# (bounded at 0).
|
||||
excessBlobGas: Long
|
||||
|
||||
#--------------------------Extensions-------------------------------
|
||||
|
||||
# RawHeader is the RLP encoding of the block's header.
|
||||
rawHeader: Bytes!
|
||||
|
||||
# Raw is the RLP encoding of the block.
|
||||
raw: Bytes!
|
||||
}
|
||||
|
||||
# CallData represents the data associated with a local contract call.
|
||||
|
@ -379,7 +439,7 @@ type SyncState{
|
|||
# Pending represents the current pending state.
|
||||
type Pending {
|
||||
# TransactionCount is the number of transactions in the pending state.
|
||||
transactionCount: Int!
|
||||
transactionCount: Long!
|
||||
|
||||
# Transactions is a list of transactions in the current pending state.
|
||||
transactions: [Transaction!]
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
per protocool folders apply, e.g.
|
||||
|
||||
- eth65/queries.toml (obsoleted *eth65* test specs)
|
||||
- eth66/queries.toml
|
||||
- ...
|
|
@ -23,6 +23,7 @@
|
|||
{"name":"Address"},
|
||||
{"name":"Block"},
|
||||
{"name":"CallResult"},
|
||||
{"name":"Withdrawal"},
|
||||
{"name":"Query"},
|
||||
{"name":"Boolean"},
|
||||
{"name":"FilterCriteria"},
|
||||
|
@ -106,38 +107,38 @@
|
|||
"""
|
||||
result = """
|
||||
{
|
||||
"chainID":1,
|
||||
"chainID":"0x1",
|
||||
"block":{
|
||||
"__typename":"Block",
|
||||
"number":3,
|
||||
"number":"0x3",
|
||||
"hash":"0x72d69cc3c74c2740c27f4becae6c9f9fc524c702a9a48d23c564b13dce5fe0a1",
|
||||
"parent":{
|
||||
"__typename":"Block",
|
||||
"number":2
|
||||
"number":"0x2"
|
||||
},
|
||||
"nonce":"0x0000000000000000",
|
||||
"transactionsRoot":"0x8c8775e959d553f9f991a21a8502dbe6819c53c518711f2cbbbd7ed998f65647",
|
||||
"transactionCount":1,
|
||||
"transactionCount":"0x1",
|
||||
"stateRoot":"0x81b1df384897709e96a4b6319fda4e8f7682a1c9d753b1fb772ed4fb19f1e443",
|
||||
"receiptsRoot":"0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
|
||||
"miner":{
|
||||
"__typename":"Account",
|
||||
"address":"0x8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"balance":"0x542253a12a8f8dc0",
|
||||
"transactionCount":0,
|
||||
"transactionCount":"0x0",
|
||||
"code":"0x",
|
||||
"storage":"0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"extraData":"0x42",
|
||||
"gasLimit":3141592,
|
||||
"gasLimit":"0x2fefd8",
|
||||
"baseFeePerGas":null,
|
||||
"gasUsed":21000,
|
||||
"gasUsed":"0x5208",
|
||||
"timestamp":"0x54c99839",
|
||||
"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"difficulty":"0x20000",
|
||||
"totalDifficulty":"0x80000",
|
||||
"ommerCount":1,
|
||||
"ommerCount":"0x1",
|
||||
"ommers":[
|
||||
{
|
||||
"__typename":"Block",
|
||||
|
@ -154,7 +155,7 @@
|
|||
"__typename":"Account",
|
||||
"address":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||
"balance":"0x1e",
|
||||
"transactionCount":0,
|
||||
"transactionCount":"0x0",
|
||||
"code":"0x",
|
||||
"storage":"0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
|
@ -226,8 +227,8 @@
|
|||
{
|
||||
"__typename":"Transaction",
|
||||
"hash":"0xbb8e2ffb7276bc688c0305d5c35ae219cf036ac7a3b058ffa9d32275cc75f31b",
|
||||
"nonce":0,
|
||||
"index":0,
|
||||
"nonce":"0x0",
|
||||
"index":"0x0",
|
||||
"from":{
|
||||
"__typename":"Account",
|
||||
"address":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"
|
||||
|
@ -238,21 +239,21 @@
|
|||
},
|
||||
"value":"0xa",
|
||||
"gasPrice":"0x3e8",
|
||||
"gas":314159,
|
||||
"gas":"0x4cb2f",
|
||||
"inputData":"0x",
|
||||
"block":{
|
||||
"__typename":"Block",
|
||||
"number":1
|
||||
"number":"0x1"
|
||||
},
|
||||
"status":1,
|
||||
"gasUsed":21000,
|
||||
"cumulativeGasUsed":21000,
|
||||
"status":"0x1",
|
||||
"gasUsed":"0x5208",
|
||||
"cumulativeGasUsed":"0x5208",
|
||||
"createdContract":null,
|
||||
"logs":[],
|
||||
"r":"0x25d49a54362b5ae38cf895fa9a1d3ded6f7d5577e572c9a93cdebff6e33ceaf7",
|
||||
"s":"0x773806df18e22db29acde1dd96c0418e28738af7f520e5e2c5c673494029e5",
|
||||
"v":"0x1b",
|
||||
"type":0,
|
||||
"type":"0x0",
|
||||
"accessList":null,
|
||||
"maxFeePerGas":null,
|
||||
"maxPriorityFeePerGas":null,
|
||||
|
@ -283,7 +284,7 @@
|
|||
"block":{
|
||||
"__typename":"Block",
|
||||
"hash":"0x72d69cc3c74c2740c27f4becae6c9f9fc524c702a9a48d23c564b13dce5fe0a1",
|
||||
"number":3
|
||||
"number":"0x3"
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
@ -304,7 +305,7 @@
|
|||
"block":{
|
||||
"__typename":"Block",
|
||||
"hash":"0x72d69cc3c74c2740c27f4becae6c9f9fc524c702a9a48d23c564b13dce5fe0a1",
|
||||
"number":3
|
||||
"number":"0x3"
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
@ -361,9 +362,9 @@
|
|||
{
|
||||
"syncing":{
|
||||
"__typename":"SyncState",
|
||||
"startingBlock":0,
|
||||
"currentBlock":3,
|
||||
"highestBlock":0,
|
||||
"startingBlock":"0x0",
|
||||
"currentBlock":"0x3",
|
||||
"highestBlock":"0x0",
|
||||
"pulledStates":null,
|
||||
"knownStates":null
|
||||
}
|
||||
|
@ -386,22 +387,22 @@
|
|||
"blocks":[
|
||||
{
|
||||
"__typename":"Block",
|
||||
"number":0,
|
||||
"number":"0x0",
|
||||
"hash":"0x2b253498ad5e63a16978753398bad1fde371a3e513438297b52d65dc98e1db29"
|
||||
},
|
||||
{
|
||||
"__typename":"Block",
|
||||
"number":1,
|
||||
"number":"0x1",
|
||||
"hash":"0xa4b71270e83c38d941d61fc2d8f3842f98a83203b82c3dea3176f1feb5a67b17"
|
||||
},
|
||||
{
|
||||
"__typename":"Block",
|
||||
"number":2,
|
||||
"number":"0x2",
|
||||
"hash":"0x579d2bdb721bde7a6bc56b53f4962a58493ee11482e8f738702ddb3d65888a74"
|
||||
},
|
||||
{
|
||||
"__typename":"Block",
|
||||
"number":3,
|
||||
"number":"0x3",
|
||||
"hash":"0x72d69cc3c74c2740c27f4becae6c9f9fc524c702a9a48d23c564b13dce5fe0a1"
|
||||
}
|
||||
]
|
||||
|
@ -426,7 +427,7 @@
|
|||
result = """
|
||||
{
|
||||
"block":{
|
||||
"estimateGas":21000
|
||||
"estimateGas":"0x5208"
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
@ -457,8 +458,8 @@
|
|||
"call":{
|
||||
"__typename":"CallResult",
|
||||
"data":"0x",
|
||||
"gasUsed":21000,
|
||||
"status":1
|
||||
"gasUsed":"0x5208",
|
||||
"status":"0x1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -471,24 +472,8 @@ mutation {
|
|||
sendRawTransaction(data: "0xf86080018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba077c7cd36820c71821c1aed59de46e70e701c4a8dd89c9ba508ab722210f60da8a03f29825d40c7c3f7bff3ca69267e0f3fb74b2d18b8c2c4e3c135b5d3b06e288d")
|
||||
}
|
||||
"""
|
||||
result = """
|
||||
{
|
||||
"sendRawTransaction":"0x4ffa559ae277813fb886d1fa8743a590ba6b699f9893de99f5d1bcea9620b278"
|
||||
}
|
||||
"""
|
||||
|
||||
[[units]]
|
||||
name = "query.protocolVersion"
|
||||
code = """
|
||||
{
|
||||
protocolVersion
|
||||
}
|
||||
"""
|
||||
result = """
|
||||
{
|
||||
"protocolVersion":66
|
||||
}
|
||||
"""
|
||||
errors = ["[2, 3]: Fatal: Field 'sendRawTransaction' cannot be resolved: \"transaction rejected by txpool\": @[\"sendRawTransaction\"]"]
|
||||
result = """null"""
|
||||
|
||||
[[units]]
|
||||
name = "query.block(number) logs"
|
|
@ -8,7 +8,7 @@
|
|||
# those terms.
|
||||
|
||||
import
|
||||
std/[os, json],
|
||||
std/[json],
|
||||
stew/byteutils,
|
||||
eth/[p2p, rlp],
|
||||
graphql, ../nimbus/graphql/ethapi, graphql/test_common,
|
||||
|
@ -25,8 +25,8 @@ type
|
|||
uncles: seq[BlockHeader]
|
||||
|
||||
const
|
||||
caseFolder = "tests" / "graphql" / "eth" & $ethVersion
|
||||
dataFolder = "tests" / "fixtures" / "eth_tests" / "BlockchainTests" / "ValidBlocks" / "bcUncleTest"
|
||||
caseFolder = "tests/graphql"
|
||||
dataFolder = "tests/fixtures/eth_tests/BlockchainTests/ValidBlocks/bcUncleTest"
|
||||
|
||||
proc toBlock(n: JsonNode, key: string): EthBlock =
|
||||
let rlpBlob = hexToSeqByte(n[key].str)
|
||||
|
@ -43,7 +43,7 @@ proc setupChain(): CommonRef =
|
|||
berlinBlock : some(10.toBlockNumber)
|
||||
)
|
||||
|
||||
var jn = json.parseFile(dataFolder / "oneUncle.json")
|
||||
var jn = json.parseFile(dataFolder & "/oneUncle.json")
|
||||
for k, v in jn:
|
||||
if v["network"].str == "Istanbul":
|
||||
jn = v
|
||||
|
|
Loading…
Reference in New Issue