Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
42085ce9
Unverified
Commit
42085ce9
authored
Sep 02, 2024
by
clabby
Committed by
GitHub
Sep 02, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore(op-service): Remove `reth` receipts source (#11706)
parent
9452aa66
Changes
21
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
3 additions
and
5802 deletions
+3
-5802
config.yml
.circleci/config.yml
+0
-43
flags.go
op-node/flags/flags.go
+0
-8
config.go
op-node/node/config.go
+0
-3
node.go
op-node/node/node.go
+0
-3
service.go
op-node/service.go
+0
-1
.gitignore
op-service/rethdb-reader/.gitignore
+0
-8
Cargo.lock
op-service/rethdb-reader/Cargo.lock
+0
-4909
Cargo.toml
op-service/rethdb-reader/Cargo.toml
+0
-26
Makefile
op-service/rethdb-reader/Makefile
+0
-8
README.md
op-service/rethdb-reader/README.md
+0
-113
headgen.sh
op-service/rethdb-reader/headgen.sh
+0
-16
rustfmt.toml
op-service/rethdb-reader/rustfmt.toml
+0
-11
db.rs
op-service/rethdb-reader/src/db.rs
+0
-59
lib.rs
op-service/rethdb-reader/src/lib.rs
+0
-47
receipts.rs
op-service/rethdb-reader/src/receipts.rs
+0
-334
block.rlp
op-service/rethdb-reader/testdata/block.rlp
+0
-0
receipts.json
op-service/rethdb-reader/testdata/receipts.json
+0
-12
eth_client.go
op-service/sources/eth_client.go
+3
-16
reth_db.go
op-service/sources/reth_db.go
+0
-125
reth_db_stub.go
op-service/sources/reth_db_stub.go
+0
-15
reth_db_test.go
op-service/sources/reth_db_test.go
+0
-45
No files found.
.circleci/config.yml
View file @
42085ce9
...
...
@@ -1313,45 +1313,6 @@ jobs:
paths
:
-
"
/go/pkg/mod"
op-service-rethdb-tests
:
docker
:
-
image
:
<<pipeline.parameters.ci_builder_rust_image>>
steps
:
-
checkout
-
check-changed
:
patterns
:
op-service,op-node
-
restore_cache
:
name
:
Restore Go modules cache
key
:
gomod-{{ checksum "go.sum" }}
-
run
:
name
:
Cargo fmt + clippy
command
:
|
cargo +nightly fmt -- --check
cargo +nightly clippy --all --all-features -- -D warnings
working_directory
:
op-service/rethdb-reader
-
run
:
name
:
Generate testdata db
command
:
cargo test
working_directory
:
op-service/rethdb-reader
-
run
:
name
:
Build dylib
command
:
cargo build --release
working_directory
:
op-service/rethdb-reader
-
run
:
name
:
Update LD_LIBRARY_PATH
command
:
echo 'export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/root/project/op-service/rethdb-reader/target/release"' >> $BASH_ENV
-
run
:
name
:
Run op-service RethDB tests
command
:
|
gotestsum --format=standard-verbose --junitfile=/tmp/test-results/op-service.xml \
-- -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out \
-run TestRethDB -tags rethdb -v
working_directory
:
op-service/sources
# TODO(CLI-148): Fix codecov
#- run:
#name: upload coverage
#command: codecov --verbose --clean --flags bedrock-rethdb-go-tests
bedrock-go-tests
:
# just a helper, that depends on all the actual test jobs
docker
:
# Use a smaller base image to avoid pulling the huge ci-builder
...
...
@@ -1622,9 +1583,6 @@ workflows:
requires
:
-
pnpm-monorepo
-
cannon-prestate
-
op-service-rethdb-tests
:
requires
:
-
go-mod-download
-
op-program-compat
:
requires
:
-
op-program-tests
...
...
@@ -1647,7 +1605,6 @@ workflows:
-
op-program-compat
-
op-service-tests
-
op-supervisor-tests
-
op-service-rethdb-tests
-
op-e2e-HTTP-tests
-
op-e2e-fault-proof-tests
-
op-e2e-action-tests
...
...
op-node/flags/flags.go
View file @
42085ce9
...
...
@@ -157,13 +157,6 @@ var (
}(),
Category
:
L1RPCCategory
,
}
L1RethDBPath
=
&
cli
.
StringFlag
{
Name
:
"l1.rethdb"
,
Usage
:
"The L1 RethDB path, used to fetch receipts for L1 blocks."
,
EnvVars
:
prefixEnvVars
(
"L1_RETHDB"
),
Hidden
:
true
,
Category
:
L1RPCCategory
,
}
L1RPCMaxConcurrency
=
&
cli
.
IntFlag
{
Name
:
"l1.max-concurrency"
,
Usage
:
"Maximum number of concurrent RPC requests to make to the L1 RPC provider."
,
...
...
@@ -413,7 +406,6 @@ var optionalFlags = []cli.Flag{
HeartbeatURLFlag
,
RollupHalt
,
RollupLoadProtocolVersions
,
L1RethDBPath
,
ConductorEnabledFlag
,
ConductorRpcFlag
,
ConductorRpcTimeoutFlag
,
...
...
op-node/node/config.go
View file @
42085ce9
...
...
@@ -65,9 +65,6 @@ type Config struct {
// Cancel to request a premature shutdown of the node itself, e.g. when halting. This may be nil.
Cancel
context
.
CancelCauseFunc
// [OPTIONAL] The reth DB path to read receipts from
RethDBPath
string
// Conductor is used to determine this node is the leader sequencer.
ConductorEnabled
bool
ConductorRpc
string
...
...
op-node/node/node.go
View file @
42085ce9
...
...
@@ -172,9 +172,6 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
return
fmt
.
Errorf
(
"failed to get L1 RPC client: %w"
,
err
)
}
// Set the RethDB path in the EthClientConfig, if there is one configured.
rpcCfg
.
EthClientConfig
.
RethDBPath
=
cfg
.
RethDBPath
n
.
l1Source
,
err
=
sources
.
NewL1Client
(
client
.
NewInstrumentedRPC
(
l1Node
,
&
n
.
metrics
.
RPCMetrics
.
RPCClientMetrics
),
n
.
log
,
n
.
metrics
.
L1SourceCache
,
rpcCfg
)
if
err
!=
nil
{
...
...
op-node/service.go
View file @
42085ce9
...
...
@@ -106,7 +106,6 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
SafeDBPath
:
ctx
.
String
(
flags
.
SafeDBPath
.
Name
),
Sync
:
*
syncConfig
,
RollupHalt
:
haltOption
,
RethDBPath
:
ctx
.
String
(
flags
.
L1RethDBPath
.
Name
),
ConductorEnabled
:
ctx
.
Bool
(
flags
.
ConductorEnabledFlag
.
Name
),
ConductorRpc
:
ctx
.
String
(
flags
.
ConductorRpcFlag
.
Name
),
...
...
op-service/rethdb-reader/.gitignore
deleted
100644 → 0
View file @
9452aa66
# Target
target/
# Bindings
rdb.h
# Testdata DB
testdata/db
op-service/rethdb-reader/Cargo.lock
deleted
100644 → 0
View file @
9452aa66
This source diff could not be displayed because it is too large. You can
view the blob
instead.
op-service/rethdb-reader/Cargo.toml
deleted
100644 → 0
View file @
9452aa66
[package]
name
=
"rethdb-reader"
description
=
"A simple library for reading data through Reth's DB abstractions."
version
=
"0.1.0"
edition
=
"2021"
[lib]
name
=
"rethdbreader"
crate-type
=
["cdylib"]
[dependencies]
# reth
reth-primitives
=
{
git
=
"https://github.com/paradigmxyz/reth.git"
,
rev
=
"e0c220e"
}
reth-provider
=
{
git
=
"https://github.com/paradigmxyz/reth.git"
,
rev
=
"e0c220e"
}
reth-db
=
{
git
=
"https://github.com/paradigmxyz/reth.git"
,
rev
=
"e0c220e"
}
reth-rpc-types
=
{
git
=
"https://github.com/paradigmxyz/reth.git"
,
rev
=
"e0c220e"
}
reth-blockchain-tree
=
{
git
=
"https://github.com/paradigmxyz/reth.git"
,
rev
=
"e0c220e"
}
# misc
serde
=
"1.0.197"
serde_json
=
"1.0.114"
anyhow
=
"1.0.80"
[dev-dependencies]
reth-revm
=
{
git
=
"https://github.com/paradigmxyz/reth.git"
,
rev
=
"e0c220e"
}
alloy-rlp
=
"0.3.4"
op-service/rethdb-reader/Makefile
deleted
100644 → 0
View file @
9452aa66
.PHONY
:
testdata
testdata
:
mkdir
-p
testdata
@
echo
"Fetching block RLP and receipts for block #18,663,292 from ethereum mainnet"
cast rpc debug_getRawBlock 0x11CC77C | jq
-r
| xxd
-r
-p
>
testdata/block.rlp
cast rpc debug_getRawReceipts 0x11CC77C | jq
-r
>
testdata/receipts.json
@
echo
"Done. Generating testdata DB & testing integrity..."
cargo
test
op-service/rethdb-reader/README.md
deleted
100644 → 0
View file @
9452aa66
# `rethdb-reader`
A dylib to be accessed via FFI in
`op-service`
's
`sources`
package for reading information
directly from the
`reth`
database.
## Developing
**Building**
To build the dylib, you must first have the
[
Rust Toolchain
][
rust-toolchain
]
installed.
```
sh
cargo build
--release
```
**Docs**
Documentation is available via rustdoc.
```
sh
cargo doc
--open
```
**Linting**
```
sh
cargo +nightly
fmt
--
&&
cargo +nightly clippy
--all
--all-features
--
-D
warnings
```
**Generating `testdata`**
The testdata block and
`reth`
database can be generated by running the
`testdata`
make directive:
```
sh
ETH_RPC_URL
=
"<your_L1_RPC_URL>"
make testdata
```
**Generating the C header**
To generate the C header, first install
`cbindgen`
via
`cargo install cbindgen --force`
. Then, run the generation script:
```
sh
./headgen.sh
```
### C Header
The C header below is generated by
`cbindgen`
, and it is the interface that consumers of the dylib use to call its exported
functions. Currently, the only exported functions pertain to reading fully hydrated block receipts from the database.
```
c
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* A [ReceiptsResult] is a wrapper around a JSON string containing serialized [TransactionReceipt]s
* as well as an error status that is compatible with FFI.
*
* # Safety
* - When the `error` field is false, the `data` pointer is guaranteed to be valid.
* - When the `error` field is true, the `data` pointer is guaranteed to be null.
*/
typedef
struct
ReceiptsResult
{
uint32_t
*
data
;
uintptr_t
data_len
;
bool
error
;
}
ReceiptsResult
;
/**
* A [OpenDBResult] is a wrapper of DB instance [BlockchainProvider]
* as well as an error status that is compatible with FFI.
*
* # Safety
* - When the `error` field is false, the `data` pointer is guaranteed to be valid.
* - When the `error` field is true, the `data` pointer is guaranteed to be null.
*/
typedef
struct
OpenDBResult
{
const
void
*
data
;
bool
error
;
}
OpenDBResult
;
/**
* Read the receipts for a blockhash from the RETH database directly.
*
* # Safety
* - All possible nil pointer dereferences are checked, and the function will return a failing
* [ReceiptsResult] if any are found.
*/
struct
ReceiptsResult
rdb_read_receipts
(
const
uint8_t
*
block_hash
,
uintptr_t
block_hash_len
,
const
void
*
db_instance
);
/**
* Free a string that was allocated in Rust and passed to C.
*
* # Safety
* - All possible nil pointer dereferences are checked.
*/
void
rdb_free_string
(
char
*
string
);
/**
* Open a DB instance and return.
*
* # Safety
* - All possible nil pointer dereferences are checked, and the function will return a failing
* [OpenDBResult] if any are found.
*/
struct
OpenDBResult
open_db_read_only
(
const
char
*
db_path
);
```
[
rust-toolchain
]:
https://rustup.rs/
op-service/rethdb-reader/headgen.sh
deleted
100755 → 0
View file @
9452aa66
#!/bin/bash
set
-e
# Generate rdb.h
cbindgen
--crate
rethdb-reader
--output
rdb.h
-l
C
# Process README.md to replace the content within the specified code block
awk
'
BEGIN { in_code_block=0; }
/^```c/ { in_code_block=1; print; next; }
/^```/ && in_code_block { in_code_block=0; while ((getline line < "rdb.h") > 0) print line; }
!in_code_block { print; }
'
README.md
>
README.tmp
&&
mv
README.tmp README.md
echo
"Generated C header successfully"
op-service/rethdb-reader/rustfmt.toml
deleted
100644 → 0
View file @
9452aa66
reorder_imports
=
true
imports_granularity
=
"Crate"
use_small_heuristics
=
"Max"
comment_width
=
100
wrap_comments
=
true
binop_separator
=
"Back"
trailing_comma
=
"Vertical"
trailing_semicolon
=
false
use_field_init_shorthand
=
true
format_code_in_doc_comments
=
true
doc_comment_code_block_width
=
100
op-service/rethdb-reader/src/db.rs
deleted
100644 → 0
View file @
9452aa66
use
anyhow
::{
anyhow
,
Result
};
use
reth_blockchain_tree
::
noop
::
NoopBlockchainTree
;
use
reth_db
::{
mdbx
::
DatabaseArguments
,
open_db_read_only
};
use
reth_primitives
::
MAINNET
;
use
reth_provider
::{
providers
::
BlockchainProvider
,
ProviderFactory
};
use
std
::{
ffi
::{
c_char
,
c_void
},
path
::
Path
,
};
/// A [OpenDBResult] is a wrapper of DB instance [BlockchainProvider]
/// as well as an error status that is compatible with FFI.
///
/// # Safety
/// - When the `error` field is false, the `data` pointer is guaranteed to be valid.
/// - When the `error` field is true, the `data` pointer is guaranteed to be null.
#[repr(C)]
pub
struct
OpenDBResult
{
pub
(
crate
)
data
:
*
const
c_void
,
pub
(
crate
)
error
:
bool
,
}
impl
OpenDBResult
{
/// Constructs a successful [OpenDBResult] from a DB instance.
pub
fn
success
(
data
:
*
const
c_void
)
->
Self
{
Self
{
data
,
error
:
false
}
}
/// Constructs a failing [OpenDBResult] with a null pointer to the data.
pub
fn
fail
()
->
Self
{
Self
{
data
:
std
::
ptr
::
null_mut
(),
error
:
true
}
}
}
/// Open and return a DB instance.
///
/// # Safety
/// - All possible nil pointer dereferences are checked, and the function will return a failing
/// [OpenDBResult] if any are found.
#[inline(always)]
pub
(
crate
)
unsafe
fn
open_db_read_only_inner
(
db_path
:
*
const
c_char
)
->
Result
<
OpenDBResult
>
{
// Convert the *const c_char to a Rust &str
let
db_path_str
=
{
if
db_path
.is_null
()
{
anyhow
::
bail!
(
"db path pointer is null"
);
}
std
::
ffi
::
CStr
::
from_ptr
(
db_path
)
}
.to_str
()
?
;
let
db
=
open_db_read_only
(
Path
::
new
(
db_path_str
),
DatabaseArguments
::
default
())
.map_err
(|
e
|
anyhow!
(
e
))
?
;
let
factory
=
ProviderFactory
::
new
(
db
,
MAINNET
.clone
());
// Create a read-only BlockChainProvider
let
provider
=
Box
::
new
(
BlockchainProvider
::
new
(
factory
,
NoopBlockchainTree
::
default
())
?
);
let
res
=
OpenDBResult
::
success
(
Box
::
into_raw
(
provider
)
as
*
const
c_void
);
Ok
(
res
)
}
op-service/rethdb-reader/src/lib.rs
deleted
100644 → 0
View file @
9452aa66
#![doc
=
include_str
!
(
"../README.md"
)]
use
db
::{
open_db_read_only_inner
,
OpenDBResult
};
use
receipts
::{
read_receipts_inner
,
ReceiptsResult
};
use
std
::
ffi
::
c_void
;
use
std
::
os
::
raw
::
c_char
;
mod
db
;
mod
receipts
;
/// Read the receipts for a blockhash from the RETH database directly.
///
/// # Safety
/// - All possible nil pointer dereferences are checked, and the function will return a failing
/// [ReceiptsResult] if any are found.
#[no_mangle]
pub
unsafe
extern
"C"
fn
rdb_read_receipts
(
block_hash
:
*
const
u8
,
block_hash_len
:
usize
,
db_instance
:
*
const
c_void
,
)
->
ReceiptsResult
{
read_receipts_inner
(
block_hash
,
block_hash_len
,
db_instance
)
.unwrap_or
(
ReceiptsResult
::
fail
())
}
/// Free a string that was allocated in Rust and passed to C.
///
/// # Safety
/// - All possible nil pointer dereferences are checked.
#[no_mangle]
pub
unsafe
extern
"C"
fn
rdb_free_string
(
string
:
*
mut
c_char
)
{
// Convert the raw pointer back to a CString and let it go out of scope,
// which will deallocate the memory.
if
!
string
.is_null
()
{
let
_
=
std
::
ffi
::
CString
::
from_raw
(
string
);
}
}
/// Open a DB instance and return.
///
/// # Safety
/// - All possible nil pointer dereferences are checked, and the function will return a failing
/// [OpenDBResult] if any are found.
#[no_mangle]
pub
unsafe
extern
"C"
fn
open_db_read_only
(
db_path
:
*
const
c_char
)
->
OpenDBResult
{
open_db_read_only_inner
(
db_path
)
.unwrap_or
(
OpenDBResult
::
fail
())
}
op-service/rethdb-reader/src/receipts.rs
deleted
100644 → 0
View file @
9452aa66
//! This module contains the logic for reading a block's fully hydrated receipts directly from the
//! [reth] database.
use
anyhow
::{
anyhow
,
Result
};
use
reth_blockchain_tree
::
noop
::
NoopBlockchainTree
;
use
reth_db
::
DatabaseEnv
;
use
reth_primitives
::{
BlockHashOrNumber
,
Receipt
,
TransactionKind
,
TransactionMeta
,
TransactionSigned
,
U128
,
U256
,
U64
,
};
use
reth_provider
::{
providers
::
BlockchainProvider
,
BlockReader
,
ReceiptProvider
};
use
reth_rpc_types
::{
Log
,
TransactionReceipt
};
use
std
::
ffi
::
c_void
;
/// A [ReceiptsResult] is a wrapper around a JSON string containing serialized [TransactionReceipt]s
/// as well as an error status that is compatible with FFI.
///
/// # Safety
/// - When the `error` field is false, the `data` pointer is guaranteed to be valid.
/// - When the `error` field is true, the `data` pointer is guaranteed to be null.
#[repr(C)]
pub
struct
ReceiptsResult
{
data
:
*
mut
char
,
data_len
:
usize
,
error
:
bool
,
}
impl
ReceiptsResult
{
/// Constructs a successful [ReceiptsResult] from a JSON string.
pub
fn
success
(
data
:
*
mut
char
,
data_len
:
usize
)
->
Self
{
Self
{
data
,
data_len
,
error
:
false
}
}
/// Constructs a failing [ReceiptsResult] with a null pointer to the data.
pub
fn
fail
()
->
Self
{
Self
{
data
:
std
::
ptr
::
null_mut
(),
data_len
:
0
,
error
:
true
}
}
}
/// Read the receipts for a blockhash from the RETH database directly.
///
/// # Safety
/// - All possible nil pointer dereferences are checked, and the function will return a failing
/// [ReceiptsResult] if any are found.
#[inline(always)]
pub
(
crate
)
unsafe
fn
read_receipts_inner
(
block_hash
:
*
const
u8
,
block_hash_len
:
usize
,
db_instance
:
*
const
c_void
,
)
->
Result
<
ReceiptsResult
>
{
// Convert the raw pointer and length back to a Rust slice
let
block_hash
:
[
u8
;
32
]
=
{
if
block_hash
.is_null
()
{
anyhow
::
bail!
(
"block_hash pointer is null"
);
}
std
::
slice
::
from_raw_parts
(
block_hash
,
block_hash_len
)
}
.try_into
()
?
;
// Create a read-only BlockChainProvider
let
provider
=
&*
(
db_instance
as
*
const
BlockchainProvider
<
DatabaseEnv
,
NoopBlockchainTree
>
);
// Fetch the block and the receipts within it
let
block
=
provider
.block_by_hash
(
block_hash
.into
())
?
.ok_or
(
anyhow!
(
"Failed to fetch block"
))
?
;
let
receipts
=
provider
.receipts_by_block
(
BlockHashOrNumber
::
Hash
(
block_hash
.into
()))
?
.ok_or
(
anyhow!
(
"Failed to fetch block receipts"
))
?
;
let
block_number
=
block
.number
;
let
base_fee
=
block
.base_fee_per_gas
;
let
block_hash
=
block
.hash_slow
();
let
receipts
=
block
.body
.into_iter
()
.zip
(
receipts
.clone
())
.enumerate
()
.map
(|(
idx
,
(
tx
,
receipt
))|
{
let
meta
=
TransactionMeta
{
tx_hash
:
tx
.hash
,
index
:
idx
as
u64
,
block_hash
,
block_number
,
base_fee
,
excess_blob_gas
:
None
,
};
build_transaction_receipt_with_block_receipts
(
tx
,
meta
,
receipt
,
&
receipts
)
})
.collect
::
<
Option
<
Vec
<
_
>>>
()
.ok_or
(
anyhow!
(
"Failed to build receipts"
))
?
;
// Convert the receipts to JSON for transport
let
mut
receipts_json
=
serde_json
::
to_string
(
&
receipts
)
?
;
// Create a ReceiptsResult with a pointer to the json-ified receipts
let
res
=
ReceiptsResult
::
success
(
receipts_json
.as_mut_ptr
()
as
*
mut
char
,
receipts_json
.len
());
// Forget the `receipts_json` string so that its memory isn't freed by the
// borrow checker at the end of this scope
std
::
mem
::
forget
(
receipts_json
);
// Prevent Rust from freeing the memory
Ok
(
res
)
}
/// Builds a hydrated [TransactionReceipt] from information in the passed transaction,
/// receipt, and block receipts.
///
/// Returns [None] if the transaction's sender could not be recovered from the signature.
#[inline(always)]
fn
build_transaction_receipt_with_block_receipts
(
tx
:
TransactionSigned
,
meta
:
TransactionMeta
,
receipt
:
Receipt
,
all_receipts
:
&
[
Receipt
],
)
->
Option
<
TransactionReceipt
>
{
let
transaction
=
tx
.clone
()
.into_ecrecovered
()
?
;
// get the previous transaction cumulative gas used
let
gas_used
=
if
meta
.index
==
0
{
receipt
.cumulative_gas_used
}
else
{
let
prev_tx_idx
=
(
meta
.index
-
1
)
as
usize
;
all_receipts
.get
(
prev_tx_idx
)
.map
(|
prev_receipt
|
receipt
.cumulative_gas_used
-
prev_receipt
.cumulative_gas_used
)
.unwrap_or_default
()
};
let
mut
res_receipt
=
TransactionReceipt
{
transaction_hash
:
Some
(
meta
.tx_hash
),
transaction_index
:
U64
::
from
(
meta
.index
),
block_hash
:
Some
(
meta
.block_hash
),
block_number
:
Some
(
U256
::
from
(
meta
.block_number
)),
from
:
transaction
.signer
(),
to
:
None
,
cumulative_gas_used
:
U256
::
from
(
receipt
.cumulative_gas_used
),
gas_used
:
Some
(
U256
::
from
(
gas_used
)),
contract_address
:
None
,
logs
:
Vec
::
with_capacity
(
receipt
.logs
.len
()),
effective_gas_price
:
U128
::
from
(
transaction
.effective_gas_price
(
meta
.base_fee
)),
transaction_type
:
tx
.transaction
.tx_type
()
.into
(),
// TODO pre-byzantium receipts have a post-transaction state root
state_root
:
None
,
logs_bloom
:
receipt
.bloom_slow
(),
status_code
:
if
receipt
.success
{
Some
(
U64
::
from
(
1
))
}
else
{
Some
(
U64
::
from
(
0
))
},
// EIP-4844 fields
blob_gas_price
:
None
,
blob_gas_used
:
None
,
// Other:
other
:
Default
::
default
(),
};
match
tx
.transaction
.kind
()
{
TransactionKind
::
Create
=>
{
res_receipt
.contract_address
=
Some
(
transaction
.signer
()
.create
(
tx
.transaction
.nonce
()));
}
TransactionKind
::
Call
(
addr
)
=>
{
res_receipt
.to
=
Some
(
*
addr
);
}
}
// get number of logs in the block
let
mut
num_logs
=
0
;
for
prev_receipt
in
all_receipts
.iter
()
.take
(
meta
.index
as
usize
)
{
num_logs
+=
prev_receipt
.logs
.len
();
}
for
(
tx_log_idx
,
log
)
in
receipt
.logs
.into_iter
()
.enumerate
()
{
let
rpclog
=
Log
{
address
:
log
.address
,
topics
:
log
.topics
,
data
:
log
.data
,
block_hash
:
Some
(
meta
.block_hash
),
block_number
:
Some
(
U256
::
from
(
meta
.block_number
)),
transaction_hash
:
Some
(
meta
.tx_hash
),
transaction_index
:
Some
(
U256
::
from
(
meta
.index
)),
log_index
:
Some
(
U256
::
from
(
num_logs
+
tx_log_idx
)),
removed
:
false
,
};
res_receipt
.logs
.push
(
rpclog
);
}
Some
(
res_receipt
)
}
#[cfg(test)]
mod
test
{
use
super
::
*
;
use
alloy_rlp
::
Decodable
;
use
reth_db
::{
database
::
Database
,
mdbx
::
DatabaseArguments
};
use
reth_primitives
::{
address
,
b256
,
bloom
,
hex
,
Address
,
Block
,
Bytes
,
ReceiptWithBloom
,
Receipts
,
SealedBlockWithSenders
,
MAINNET
,
U8
,
};
use
reth_provider
::{
BlockWriter
,
BundleStateWithReceipts
,
DatabaseProvider
};
use
reth_revm
::
revm
::
db
::
BundleState
;
use
std
::{
ffi
::{
c_char
,
CString
},
fs
::
File
,
path
::
Path
,
};
#[inline]
fn
dummy_block_with_receipts
()
->
Result
<
(
Block
,
Vec
<
Receipt
>
)
>
{
// To generate testdata (block 18,663,292 on Ethereum Mainnet):
// 1. BLOCK RLP: `cast rpc debug_getRawBlock 0x11CC77C | jq -r | xxd -r -p >
// testdata/block.rlp`
// 2. RECEIPTS RLP: `cast rpc debug_getRawReceipts 0x11CC77C | jq -r >
// testdata/receipts.json`
let
block_rlp
=
include_bytes!
(
"../testdata/block.rlp"
);
let
block
=
Block
::
decode
(
&
mut
block_rlp
.as_ref
())
?
;
let
receipt_rlp
:
Vec
<
Vec
<
u8
>>
=
serde_json
::
from_str
(
include_str!
(
"../testdata/receipts.json"
))
.map
(|
v
:
Vec
<
String
>
|
{
v
.into_iter
()
.map
(|
s
|
hex
::
decode
(
s
))
.collect
::
<
Result
<
Vec
<
Vec
<
u8
>>
,
_
>>
()
})
??
;
let
receipts
=
receipt_rlp
.iter
()
.map
(|
r
|
ReceiptWithBloom
::
decode
(
&
mut
r
.as_slice
())
.map
(|
r
|
r
.receipt
))
.collect
::
<
Result
<
Vec
<
Receipt
>
,
_
>>
()
?
;
Ok
((
block
,
receipts
))
}
#[inline]
fn
open_receipts_testdata_db
()
->
Result
<
()
>
{
if
File
::
open
(
"testdata/db"
)
.is_ok
()
{
return
Ok
(());
}
// Open a RW handle to the MDBX database
let
db
=
reth_db
::
init_db
(
Path
::
new
(
"testdata/db"
),
DatabaseArguments
::
default
())
.map_err
(|
e
|
anyhow!
(
e
))
?
;
let
pr
=
DatabaseProvider
::
new_rw
(
db
.tx_mut
()
?
,
MAINNET
.clone
());
// Grab the dummy block and receipts
let
(
mut
block
,
receipts
)
=
dummy_block_with_receipts
()
?
;
// Patch: The block's current state root expects the rest of the chain history to be in the
// DB; manually override it. Otherwise, the DatabaseProvider will fail to commit the
// block.
block
.header.state_root
=
reth_primitives
::
constants
::
EMPTY_ROOT_HASH
;
// Fetch the block number and tx senders for bundle state creation.
let
block_number
=
block
.header.number
;
let
senders
=
block
.body
.iter
()
.map
(|
tx
|
tx
.recover_signer
())
.collect
::
<
Option
<
Vec
<
Address
>>>
()
.ok_or
(
anyhow!
(
"Failed to recover signers"
))
?
;
// Commit the bundle state to the database
pr
.append_blocks_with_state
(
vec!
[
SealedBlockWithSenders
{
block
:
block
.seal_slow
(),
senders
}],
BundleStateWithReceipts
::
new
(
BundleState
::
default
(),
Receipts
::
from_block_receipt
(
receipts
),
block_number
,
),
Default
::
default
(),
Default
::
default
(),
None
,
)
?
;
pr
.commit
()
?
;
Ok
(())
}
#[test]
fn
fetch_receipts
()
{
open_receipts_testdata_db
()
.unwrap
();
unsafe
{
let
res
=
crate
::
open_db_read_only
(
CString
::
new
(
"testdata/db"
)
.unwrap
()
.into_raw
()
as
*
const
c_char
);
assert_eq!
(
res
.error
,
false
);
let
mut
block_hash
=
b256!
(
"6a229123d607c2232a8b0bdd36f90745945d05181018e64e60ff2b93ab6b52e5"
);
let
receipts_res
=
super
::
read_receipts_inner
(
block_hash
.as_mut_ptr
(),
32
,
res
.data
)
.unwrap
();
let
receipts_data
=
std
::
slice
::
from_raw_parts
(
receipts_res
.data
as
*
const
u8
,
receipts_res
.data_len
);
let
receipt
=
{
let
mut
receipts
:
Vec
<
TransactionReceipt
>
=
serde_json
::
from_slice
(
receipts_data
)
.unwrap
();
receipts
.remove
(
0
)
};
// Check the first receipt in the block for validity
assert_eq!
(
receipt
.transaction_type
,
U8
::
from
(
2
));
assert_eq!
(
receipt
.status_code
,
Some
(
U64
::
from
(
1
)));
assert_eq!
(
receipt
.cumulative_gas_used
,
U256
::
from
(
115_316
));
assert_eq!
(
receipt
.logs_bloom
,
bloom!
(
"00200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010"
));
assert_eq!
(
receipt
.logs
[
0
]
.address
,
address!
(
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
)
);
assert_eq!
(
receipt
.logs
[
0
]
.topics
[
0
],
b256!
(
"ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
)
);
assert_eq!
(
receipt
.logs
[
0
]
.topics
[
1
],
b256!
(
"00000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40"
)
);
assert_eq!
(
receipt
.logs
[
0
]
.data
,
Bytes
::
from_static
(
hex!
(
"00000000000000000000000000000000000000000000000008a30cd230000000"
)
.as_slice
()
)
);
assert_eq!
(
receipt
.from
,
address!
(
"41d3ab85aafed2ef9e644cb7d3bbca2fc4d8cac8"
));
assert_eq!
(
receipt
.to
,
Some
(
address!
(
"00000000003b3cc22af3ae1eac0440bcee416b40"
)));
assert_eq!
(
receipt
.transaction_hash
,
Some
(
b256!
(
"88b2d153a4e893ba91ac235325c44b1aa0c802fcb42657701e1a73e1c675f7ca"
))
);
assert_eq!
(
receipt
.block_number
,
Some
(
U256
::
from
(
18_663_292
)));
assert_eq!
(
receipt
.block_hash
,
Some
(
block_hash
));
assert_eq!
(
receipt
.transaction_index
,
U64
::
from
(
0
));
crate
::
rdb_free_string
(
receipts_res
.data
as
*
mut
c_char
);
}
}
}
op-service/rethdb-reader/testdata/block.rlp
deleted
100644 → 0
View file @
9452aa66
File deleted
op-service/rethdb-reader/testdata/receipts.json
deleted
100644 → 0
View file @
9452aa66
[
"0xb903c202f903be018301c274b9010000200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010f902b3f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000000000000000000008a30cd230000000f89b94d10bc8517059e51b625e1e57a60b348d552f685df863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a000000000000000000000000000000000000000000000000000007921e915b684f879945c1694c8168668c11777909c79142dc9d992788fe1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840000000000000000000000000000000000000000000000001129c9861392306df000000000000000000000000000000000000000000000000000e9d834abd9cdff8fc945c1694c8168668c11777909c79142dc9d992788ff863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40b88000000000000000000000000000000000000000000000000008a30cd2300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007921e915b684"
,
"0xb9043e02f9043a0183042135b9010000200000000000000000000080001000100000000000000000000000000000000000000000000000000000000000100002000000080000000000000000010000000000000000010000000008000000200000000400100000000000008000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000101000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000002000000000000000000000000000000000000001000000000000000000000200000000000008000000000020000000000000000400000000000000010f9032ff87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109ca00000000000000000000000002ec705d306b51e486b1bc0d6ebee708e0661add1a00000000000000000000000000000000000000000000000000bd0c7ca01c48000f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000002ec705d306b51e486b1bc0d6ebee708e0661add1a00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa00000000000000000000000000000000000000000000000000bd0c7ca01c48000f89b94d10bc8517059e51b625e1e57a60b348d552f685df863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa00000000000000000000000001f3c8f19ab956457994de1d50eb0ae7d057f77f8a0000000000000000000000000000000000000000000000000000099e622c10336f879945c1694c8168668c11777909c79142dc9d992788fe1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000000011e6d602b3ae786df000000000000000000000000000000000000000000000000000e039d27fc99a9f8fc945c1694c8168668c11777909c79142dc9d992788ff863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a00000000000000000000000002ec705d306b51e486b1bc0d6ebee708e0661add1a00000000000000000000000001f3c8f19ab956457994de1d50eb0ae7d057f77f8b8800000000000000000000000000000000000000000000000000bd0c7ca01c4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099e622c10336"
,
"0xb903c202f903be018305b26fb9010000200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010f902b3f89b94d10bc8517059e51b625e1e57a60b348d552f685df863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000000000000000000000007921e99216a0f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a00000000000000000000000000000000000000000000000000953f38350000000f879945c1694c8168668c11777909c79142dc9d992788fe1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b84000000000000000000000000000000000000000000000000115196ca7eae786df000000000000000000000000000000000000000000000000000e7cbf118eb049f8fc945c1694c8168668c11777909c79142dc9d992788ff863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40b880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007921e99216a00000000000000000000000000000000000000000000000000953f383500000000000000000000000000000000000000000000000000000000000000000000000"
,
"0xb90bdf02f90bdb01830b2215b9010000200000002000000000000080000000000000000000000001010000000004000000000000000000420000000000010002000000080020002000000000200800000000000000080800000008000000200090000000000000080000408040000000000000000000000008084000000000000000000000000010010050000800000800800000000000000000000000000000000000000000080000004000100000020100000000000000100080000004000000000000020000000000000000000000400002000000000000000000000000000000000000001000000000002000400012200000800000020404000000000000020000008000000000000000000010f90ad0f89b941111111254eeb25477b68fb85ed929f73a960582f842a0b9ed0243fdf00f0545c63a0af8850c090d86bb46682baec4bf3c496814fe4f02a000000000000000000000000058c1c6a484ef2d6b0f8d93b2dbeb72f3c3e9ceb5b8402511106c0eade4c289445ac7275a89e6e088cc2cb5e313a42712b2987c2fb8d30000000000000000000000000000000000000000000000000000000000000001f89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000058c1c6a484ef2d6b0f8d93b2dbeb72f3c3e9ceb5a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa000000000000000000000000000000000000000000000000000000002f0174a58f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdba0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa000000000000000000000000000000000000000000000143c3719a34f04e020edf89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa000000000000000000000000006da0fd433c1a5d7a4faa01111c044910a184553a000000000000000000000000000000000000000000000000000000000da1b3bf5f89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa00000000000000000000000000d4a11d5eeaac28ec3f61d100daf4d40471f1852a00000000000000000000000000000000000000000000000000000000215fc0e63f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000006da0fd433c1a5d7a4faa01111c044910a184553a0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdba00000000000000000000000000000000000000000000000001913572822ee731ff8799406da0fd433c1a5d7a4faa01111c044910a184553e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000000b3986c20be3ddb96f70000000000000000000000000000000000000000000000000000061647f821daf8fc9406da0fd433c1a5d7a4faa01111c044910a184553f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdbb880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000da1b3bf50000000000000000000000000000000000000000000000001913572822ee731f0000000000000000000000000000000000000000000000000000000000000000f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000d4a11d5eeaac28ec3f61d100daf4d40471f1852a0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdba00000000000000000000000000000000000000000000000003d5ec06d1b711bcff879940d4a11d5eeaac28ec3f61d100daf4d40471f1852e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000004724d25b9c0c67a0c7800000000000000000000000000000000000000000000000000002694ca870b04f8fc940d4a11d5eeaac28ec3f61d100daf4d40471f1852f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdbb88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000215fc0e630000000000000000000000000000000000000000000000003d5ec06d1b711bcf0000000000000000000000000000000000000000000000000000000000000000f9011c94a050f7adc241afa59ad5f343eaf4faf5f30a4cdbf863a0c42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781ab8a0000000000000000000000000000000000000000000000000567217953e5f8eeeffffffffffffffffffffffffffffffffffffffffffffebc3c8e65cb0fb1fdf13000000000000000000000000000000000000007b89284efd1b25e6f5f0dcbf2e000000000000000000000000000000000000000000000aa86d459fd0c59c2a59000000000000000000000000000000000000000000000000000000000001784ff89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a0000000000000000000000000000000000000000000001375a0d26e739f71f370f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a00000000000000000000000001111111254eeb25477b68fb85ed929f73a960582a0000000000000000000000000000000000000000000001375a0d26e739f71f370f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a00000000000000000000000001111111254eeb25477b68fb85ed929f73a960582a00000000000000000000000000000000000000000000000000000000000000000f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a000000000000000000000000058c1c6a484ef2d6b0f8d93b2dbeb72f3c3e9ceb5a0000000000000000000000000000000000000000000001375a0d26e739f71f370"
,
"0xb905cf02f905cb01830e0902b9010000200000008020000000000280004000000000000000000000000000000000000000200000000000000000200080000002000000080000000000000800000000000000000000000100000008040000200004000000000000000000008000004000000000000000000000000000000400240000000000000004000010000000000000000000000000000001010000000200000001000000080000004000000400002000000000004002020000000000000000000000000000002000000000000000000002000000000000000000000040000000000000001000000000000000000000200000000000000000000000000000000001000400400000000080010000f904c0f87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109ca0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a000000000000000000000000000000000000000000000000001617eb90b26c000f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a0000000000000000000000000e090e0518ea17607a01e9286522655808c3f8919a000000000000000000000000000000000000000000000000001617eb90b26c000f89b94f83e0399fd7ef1c9c1a3dbc0a4d586edc3c8d125f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e090e0518ea17607a01e9286522655808c3f8919a0000000000000000000000000faa04b4d06297dca749c2ac7783211638de3e491a000000000000000000000000000000000000000000000019d0da576764721e7e7f87994e090e0518ea17607a01e9286522655808c3f8919e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000000001e6d6c84d2f7cd2b00000000000000000000000000000000000000000000220ae8d75c1df124f53df8fc94e090e0518ea17607a01e9286522655808c3f8919f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a0000000000000000000000000c6265979793435b496e28e61af1500c22c3ba277a0000000000000000000000000faa04b4d06297dca749c2ac7783211638de3e491b88000000000000000000000000000000000000000000000000001617eb90b26c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019d0da576764721e7e7f87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a06cb8c9cbcedb37b7d125170f5d929dbbdb3203c8fd4d60356b496fa31f77fd00b8400000000000000000000000000000000000000000000000000001c4793ec69800000000000000000000000000000000000000000000000000000000000000008ef87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a00c2a2f565c7774c59e49ef6b3c255329f4d254147e06e724d3a8569bb7bd21adb8400000000000000000000000000000000000000000000000000001c4793ec69800000000000000000000000000faa04b4d06297dca749c2ac7783211638de3e491f89994db5889e35e379ef0498aae126fc2cce1fbd23216e1a09f849d23f4955d98202378ea318f2b0c7533695d3c9fb2a3931f0f919fa8c420b86000000000000000000000000000000000000000000000000001617eb90b26c00000000000000000000000000000000000000000000000019d0da576764721e7e700000000000000000000000000000000000000000000019d0da576764721e7e7"
,
"0xf905cb0183105d5cb90100000000000180a0000004000000004000000000000001000000000000002200000000000000000000080200200000000002000000080020000000000800000000000000000000000900000008040000000000000000400000000000000000004000000000000000000000000000000400240000000000040000000010000804000000000000000000000080010000000000000000000000008000000000000480000000000000004002000000000000000000000000000000000000000000008000000002080000000000000000000000000000000000000000000002000000000000200000000000000000000000000000000000000000000000000000010000f904c0f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000009e31efffe1e016f514f774f43d91a85ebbc11564a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a00000000000000000000000000000000000000000000000000e803e90becaf29bf89b949dd5f5dae94633760b3125a7490ecb4571d09a42f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000087033ad96757ecd730aa1652b1a7dabcc5ffb182a00000000000000000000000009e31efffe1e016f514f774f43d91a85ebbc11564a0000000000000000000000000000000000000000000acb37f48fe24c23d1833c6f9011c949e31efffe1e016f514f774f43d91a85ebbc11564f863a0c42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216b8a0000000000000000000000000000000000000000000acb37f48fe24c23d1833c6fffffffffffffffffffffffffffffffffffffffffffffffff17fc16f41350d65000000000000000000000000000000000000000000049c65546ad3eed1521a58000000000000000000000000000000000000000000009404a8bb774136003dadfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd14eff87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a00000000000000000000000000000000000000000000000000e803e90becaf29bf87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a06cb8c9cbcedb37b7d125170f5d929dbbdb3203c8fd4d60356b496fa31f77fd00b84000000000000000000000000000000000000000000000000000128fac3e64dad00000000000000000000000000000000000000000000000000000000000000012f87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a00c2a2f565c7774c59e49ef6b3c255329f4d254147e06e724d3a8569bb7bd21adb84000000000000000000000000000000000000000000000000000128fac3e64dad000000000000000000000000087033ad96757ecd730aa1652b1a7dabcc5ffb182f89994db5889e35e379ef0498aae126fc2cce1fbd23216e1a09f849d23f4955d98202378ea318f2b0c7533695d3c9fb2a3931f0f919fa8c420b860000000000000000000000000000000000000000000acb37f48fe24c23d1833c60000000000000000000000000000000000000000000000000e803e90becaf29b0000000000000000000000000000000000000000000000000e803e90becaf29bf85894db5889e35e379ef0498aae126fc2cce1fbd23216e1a0522881958b3c4a6fc0840ad3b7fb947b881edc28c004245a62541647422ade97a00000000000000000000000000000000000000000000000000e803e90becaf29b"
,
"0xb903e402f903e00183128fdcb9010000000000010000000000000000000000000000000000010000000000040000000000000000000000000008000000000002000000080020000000000000000000000000000000000808000008000000000000000000410000000000000000000000000000000000000000040000000000000000000000040000000010000800000000000000000000200000000000000000000000010000000000000000000000000000000000200000000000010000000000000000000000002000000008000000000002000000000000080000000000000000000000000000000002000000000000200000000000000010000000000000000000000000000000000000000000f902d5f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195a000000000000000000000000000000000000000000000000000b5762b8f483dbff89b94a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000f706190050f8c7d62021d5ba52871640ea9fd3fea000000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640a0000000000000000000000000000000000000000000000000000000000629852ff9011c9488e6a0c2ddd26feeb64f039a2c41296fcb3f5640f863a0c42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195b8a0000000000000000000000000000000000000000000000000000000000629852fffffffffffffffffffffffffffffffffffffffffffffffffff4a89d470b7c24100000000000000000000000000000000000056d8c2fe7c57e75b18c386394ff90000000000000000000000000000000000000000000000016397a5e7cf05707c0000000000000000000000000000000000000000000000000000000000030e04f87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195a000000000000000000000000000000000000000000000000000b5762b8f483dbf"
,
"0xb901ab02f901a701831345f7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000200000000000000000000000004000000000008000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000080000000000000008000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000001000000000000000000000000000000000000f89df89b9496add417293a49e80f024734e96cfd8b355bcc14f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000af56ec1d3a54e9d05fbe2bc158219a810890dc77a0000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"0xb9053d02f90539018315a059b9010000210000000000100000100080000000000000000000000080000000000000000000000000000000000000000000000002010000080000000000000000080000000020080000800000000008000000208000000000400000000000000020000000000000000000000000000000000000000000000000040000000010000000000040004000000000000000000000000000000000000000080000004000000000000000000000000000000000000000000400000000080000000000000008000000000002000000000000000000000000000400400000101000000002000202000000200000000000000000000001000000001000000000000000000000000400f9042ef8fd94000000000022d473030f116ddee9f6b43ac78ba3f884a0c6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708eca0000000000000000000000000af56ec1d3a54e9d05fbe2bc158219a810890dc77a000000000000000000000000096add417293a49e80f024734e96cfd8b355bcc14a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fadb860000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000658c27210000000000000000000000000000000000000000000000000000000000000000f89b9496add417293a49e80f024734e96cfd8b355bcc14f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000af56ec1d3a54e9d05fbe2bc158219a810890dc77a00000000000000000000000000bee64a7c035fa2f69b9a6cad5d761de038ecb02a000000000000000000000000000000000000000000000000c83b84b800fe98c96f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000bee64a7c035fa2f69b9a6cad5d761de038ecb02a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fada000000000000000000000000000000000000000000000000001e7841cb75e9302f879940bee64a7c035fa2f69b9a6cad5d761de038ecb02e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840000000000000000000000000000000000000000000004581511bfd43276c16b400000000000000000000000000000000000000000000000a99e131364ae486cff8fc940bee64a7c035fa2f69b9a6cad5d761de038ecb02f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fada00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fadb88000000000000000000000000000000000000000000000000c83b84b800fe98c960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e7841cb75e9302f87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fada000000000000000000000000000000000000000000000000001e7841cb75e9302"
,
"0xb9010d02f90109018315f261b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"
]
op-service/sources/eth_client.go
View file @
42085ce9
...
...
@@ -11,6 +11,7 @@ package sources
import
(
"context"
"errors"
"fmt"
"math/big"
"time"
...
...
@@ -62,11 +63,6 @@ type EthClientConfig struct {
// till we re-attempt the user-preferred methods.
// If this is 0 then the client does not fall back to less optimal but available methods.
MethodResetDuration
time
.
Duration
// [OPTIONAL] The reth DB path to fetch receipts from.
// If it is specified, the rethdb receipts fetcher will be used
// and the RPC configuration parameters don't need to be set.
RethDBPath
string
}
func
(
c
*
EthClientConfig
)
Check
()
error
{
...
...
@@ -82,15 +78,6 @@ func (c *EthClientConfig) Check() error {
if
c
.
PayloadsCacheSize
<
0
{
return
fmt
.
Errorf
(
"invalid payloads cache size: %d"
,
c
.
PayloadsCacheSize
)
}
if
c
.
RethDBPath
!=
""
{
if
buildRethdb
{
// If the rethdb path is set, we use the rethdb receipts fetcher and skip creating
// an RCP receipts fetcher, so below rpc config parameters don't need to be checked.
return
nil
}
else
{
return
fmt
.
Errorf
(
"rethdb path specified, but built without rethdb support"
)
}
}
if
c
.
MaxConcurrentRequests
<
1
{
return
fmt
.
Errorf
(
"expected at least 1 concurrent request, but max is %d"
,
c
.
MaxConcurrentRequests
)
}
...
...
@@ -136,9 +123,9 @@ func NewEthClient(client client.RPC, log log.Logger, metrics caching.Metrics, co
}
client
=
LimitRPC
(
client
,
config
.
MaxConcurrentRequests
)
recProvider
:=
newRecProviderFromConfig
(
client
,
log
,
metrics
,
config
)
recProvider
:=
newR
PCR
ecProviderFromConfig
(
client
,
log
,
metrics
,
config
)
if
recProvider
.
isInnerNil
()
{
return
nil
,
fmt
.
Errorf
(
"failed to open RethDB
"
)
return
nil
,
errors
.
New
(
"failed to establish receipts provider
"
)
}
return
&
EthClient
{
client
:
client
,
...
...
op-service/sources/reth_db.go
deleted
100644 → 0
View file @
9452aa66
//go:build rethdb
package
sources
import
(
"context"
"encoding/json"
"fmt"
"unsafe"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources/caching"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
)
/*
#cgo LDFLAGS: -L../rethdb-reader/target/release -lrethdbreader
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
char* data;
size_t data_len;
bool error;
} ReceiptsResult;
typedef struct OpenDBResult {
const void *data;
bool error;
} OpenDBResult;
extern ReceiptsResult rdb_read_receipts(const uint8_t* block_hash, size_t block_hash_len, const void *db_instance);
extern void rdb_free_string(char* string);
extern OpenDBResult open_db_read_only(const char *db_path);
*/
import
"C"
// FetchRethReceipts fetches the receipts for the given block hash directly from the Reth Database
// and populates the given results slice pointer with the receipts that were found.
func
FetchRethReceipts
(
db
unsafe
.
Pointer
,
blockHash
*
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
if
blockHash
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Must provide a block hash to fetch receipts for."
)
}
// Convert the block hash to a C byte array and defer its deallocation
cBlockHash
:=
C
.
CBytes
(
blockHash
[
:
])
defer
C
.
free
(
cBlockHash
)
// Call the C function to fetch the receipts from the Reth Database
receiptsResult
:=
C
.
rdb_read_receipts
((
*
C
.
uint8_t
)(
cBlockHash
),
C
.
size_t
(
len
(
blockHash
)),
db
)
if
receiptsResult
.
error
{
return
nil
,
fmt
.
Errorf
(
"Error fetching receipts from Reth Database."
)
}
// Free the memory allocated by the C code
defer
C
.
rdb_free_string
(
receiptsResult
.
data
)
// Convert the returned JSON string to Go string and parse it
receiptsJSON
:=
C
.
GoStringN
(
receiptsResult
.
data
,
C
.
int
(
receiptsResult
.
data_len
))
var
receipts
types
.
Receipts
if
err
:=
json
.
Unmarshal
([]
byte
(
receiptsJSON
),
&
receipts
);
err
!=
nil
{
return
nil
,
err
}
return
receipts
,
nil
}
func
OpenDBReadOnly
(
dbPath
string
)
(
db
unsafe
.
Pointer
,
err
error
)
{
// Convert the db path to a C string and defer its deallocation
cDbPath
:=
C
.
CString
(
dbPath
)
defer
C
.
free
(
unsafe
.
Pointer
(
cDbPath
))
// Call the C function to fetch the receipts from the Reth Database
openDBResult
:=
C
.
open_db_read_only
(
cDbPath
)
if
openDBResult
.
error
{
return
nil
,
fmt
.
Errorf
(
"failed to open RethDB"
)
}
return
openDBResult
.
data
,
nil
}
type
RethDBReceiptsFetcher
struct
{
dbInstance
unsafe
.
Pointer
}
var
_
ReceiptsProvider
=
(
*
RethDBReceiptsFetcher
)(
nil
)
// NewRethDBReceiptsFetcher opens a RethDB for reading receipts. It returns nil if it was unable to open the database
func
NewRethDBReceiptsFetcher
(
dbPath
string
)
*
RethDBReceiptsFetcher
{
db
,
err
:=
OpenDBReadOnly
(
dbPath
)
if
err
!=
nil
{
return
nil
}
return
&
RethDBReceiptsFetcher
{
dbInstance
:
db
,
}
}
func
(
f
*
RethDBReceiptsFetcher
)
FetchReceipts
(
ctx
context
.
Context
,
block
eth
.
BlockInfo
,
txHashes
[]
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
if
f
.
dbInstance
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Reth dbInstance is nil"
)
}
hash
:=
block
.
Hash
()
return
FetchRethReceipts
(
f
.
dbInstance
,
&
hash
)
}
func
NewCachingRethDBReceiptsFetcher
(
dbPath
string
,
m
caching
.
Metrics
,
cacheSize
int
)
*
CachingReceiptsProvider
{
return
NewCachingReceiptsProvider
(
NewRethDBReceiptsFetcher
(
dbPath
),
m
,
cacheSize
)
}
const
buildRethdb
=
true
func
newRecProviderFromConfig
(
client
client
.
RPC
,
log
log
.
Logger
,
metrics
caching
.
Metrics
,
config
*
EthClientConfig
)
*
CachingReceiptsProvider
{
if
dbPath
:=
config
.
RethDBPath
;
dbPath
!=
""
{
return
NewCachingRethDBReceiptsFetcher
(
dbPath
,
metrics
,
config
.
ReceiptsCacheSize
)
}
return
newRPCRecProviderFromConfig
(
client
,
log
,
metrics
,
config
)
}
op-service/sources/reth_db_stub.go
deleted
100644 → 0
View file @
9452aa66
//go:build !rethdb
package
sources
import
(
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/sources/caching"
"github.com/ethereum/go-ethereum/log"
)
const
buildRethdb
=
false
func
newRecProviderFromConfig
(
client
client
.
RPC
,
log
log
.
Logger
,
metrics
caching
.
Metrics
,
config
*
EthClientConfig
)
*
CachingReceiptsProvider
{
return
newRPCRecProviderFromConfig
(
client
,
log
,
metrics
,
config
)
}
op-service/sources/reth_db_test.go
deleted
100644 → 0
View file @
9452aa66
//go:build rethdb
package
sources
import
(
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
)
func
TestRethDBReceiptsLoad
(
t
*
testing
.
T
)
{
t
.
Parallel
()
// ETH Mainnet block #18,663,292
//
// https://etherscan.io/tx/0x88b2d153a4e893ba91ac235325c44b1aa0c802fcb42657701e1a73e1c675f7ca
//
// NOTE: The block hash differs from the live block due to a state root mismatch. In order to generate
// a testdata database with only this block in it, the state root of the block was modified.
// Old State Root: 0xaf81a692d228d56d35c80d65aeba59636b4671403054f6c57446c0e3e4d951c8
// New State Root (Empty MPT): 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
blockHash
:=
common
.
HexToHash
(
"0x6a229123d607c2232a8b0bdd36f90745945d05181018e64e60ff2b93ab6b52e5"
)
fetcher
:=
NewRethDBReceiptsFetcher
(
"../rethdb-reader/testdata/db"
)
require
.
NotNil
(
t
,
fetcher
.
dbInstance
)
res
,
err
:=
FetchRethReceipts
(
fetcher
.
dbInstance
,
&
blockHash
)
require
.
NoError
(
t
,
err
)
receipt
:=
(
*
types
.
Receipt
)(
res
[
0
])
require
.
Equal
(
t
,
receipt
.
Type
,
uint8
(
2
))
require
.
Equal
(
t
,
receipt
.
Status
,
uint64
(
1
))
require
.
Equal
(
t
,
receipt
.
CumulativeGasUsed
,
uint64
(
115
_316
))
require
.
Equal
(
t
,
receipt
.
Bloom
,
types
.
BytesToBloom
(
common
.
FromHex
(
"00200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010"
)))
require
.
Equal
(
t
,
receipt
.
Logs
[
0
]
.
Address
,
common
.
HexToAddress
(
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
))
require
.
Equal
(
t
,
receipt
.
Logs
[
0
]
.
Topics
[
0
],
common
.
HexToHash
(
"ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
))
require
.
Equal
(
t
,
receipt
.
Logs
[
0
]
.
Topics
[
1
],
common
.
HexToHash
(
"00000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40"
))
require
.
Equal
(
t
,
receipt
.
Logs
[
0
]
.
Data
,
common
.
FromHex
(
"00000000000000000000000000000000000000000000000008a30cd230000000"
))
require
.
Equal
(
t
,
receipt
.
TxHash
,
common
.
HexToHash
(
"0x88b2d153a4e893ba91ac235325c44b1aa0c802fcb42657701e1a73e1c675f7ca"
))
require
.
Equal
(
t
,
receipt
.
BlockHash
,
blockHash
)
require
.
Equal
(
t
,
receipt
.
BlockNumber
,
big
.
NewInt
(
18
_663_292
))
require
.
Equal
(
t
,
receipt
.
TransactionIndex
,
uint
(
0
))
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment