Merge branch 'master' into eip7685/empty-req

This commit is contained in:
Sina Mahmoodi 2025-01-15 16:19:26 +01:00
commit 0afc3dde89
72 changed files with 508 additions and 528 deletions

View file

@ -3,9 +3,6 @@
run: run:
timeout: 20m timeout: 20m
tests: true tests: true
# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs-use-default: true
linters: linters:
disable-all: true disable-all: true
@ -54,6 +51,9 @@ linters-settings:
exclude: [""] exclude: [""]
issues: issues:
# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
exclude-dirs-use-default: true
exclude-files: exclude-files:
- core/genesis_alloc.go - core/genesis_alloc.go
exclude-rules: exclude-rules:

125
README.md
View file

@ -54,14 +54,14 @@ on how you can run your own `geth` instance.
Minimum: Minimum:
* CPU with 2+ cores * CPU with 4+ cores
* 4GB RAM * 8GB RAM
* 1TB free storage space to sync the Mainnet * 1TB free storage space to sync the Mainnet
* 8 MBit/sec download Internet service * 8 MBit/sec download Internet service
Recommended: Recommended:
* Fast CPU with 4+ cores * Fast CPU with 8+ cores
* 16GB+ RAM * 16GB+ RAM
* High-performance SSD with at least 1TB of free space * High-performance SSD with at least 1TB of free space
* 25+ MBit/sec download Internet service * 25+ MBit/sec download Internet service
@ -138,8 +138,6 @@ export your existing configuration:
$ geth --your-favourite-flags dumpconfig $ geth --your-favourite-flags dumpconfig
``` ```
*Note: This works only with `geth` v1.6.0 and above.*
#### Docker quick start #### Docker quick start
One of the quickest ways to get Ethereum up and running on your machine is by using One of the quickest ways to get Ethereum up and running on your machine is by using
@ -187,7 +185,6 @@ HTTP based JSON-RPC API options:
* `--ws.api` API's offered over the WS-RPC interface (default: `eth,net,web3`) * `--ws.api` API's offered over the WS-RPC interface (default: `eth,net,web3`)
* `--ws.origins` Origins from which to accept WebSocket requests * `--ws.origins` Origins from which to accept WebSocket requests
* `--ipcdisable` Disable the IPC-RPC server * `--ipcdisable` Disable the IPC-RPC server
* `--ipcapi` API's offered over the IPC-RPC interface (default: `admin,debug,eth,miner,net,personal,txpool,web3`)
* `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it) * `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it)
You'll need to use your own programming environments' capabilities (libraries, tools, etc) to You'll need to use your own programming environments' capabilities (libraries, tools, etc) to
@ -206,118 +203,14 @@ APIs!**
Maintaining your own private network is more involved as a lot of configurations taken for Maintaining your own private network is more involved as a lot of configurations taken for
granted in the official networks need to be manually set up. granted in the official networks need to be manually set up.
#### Defining the private genesis state Unfortunately since [the Merge](https://ethereum.org/en/roadmap/merge/) it is no longer possible
to easily set up a network of geth nodes without also setting up a corresponding beacon chain.
First, you'll need to create the genesis state of your networks, which all nodes need to be There are three different solutions depending on your use case:
aware of and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`):
```json * If you are looking for a simple way to test smart contracts from go in your CI, you can use the [Simulated Backend](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings#blockchain-simulator).
{ * If you want a convenient single node environment for testing, you can use our [Dev Mode](https://geth.ethereum.org/docs/developers/dapp-developer/dev-mode).
"config": { * If you are looking for a multiple node test network, you can set one up quite easily with [Kurtosis](https://geth.ethereum.org/docs/fundamentals/kurtosis).
"chainId": <arbitrary positive integer>,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"londonBlock": 0
},
"alloc": {},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}
```
The above fields should be fine for most purposes, although we'd recommend changing
the `nonce` to some random value so you prevent unknown remote nodes from being able
to connect to you. If you'd like to pre-fund some accounts for easier testing, create
the accounts and populate the `alloc` field with their addresses.
```json
"alloc": {
"0x0000000000000000000000000000000000000001": {
"balance": "111111111"
},
"0x0000000000000000000000000000000000000002": {
"balance": "222222222"
}
}
```
With the genesis state defined in the above JSON file, you'll need to initialize **every**
`geth` node with it prior to starting it up to ensure all blockchain parameters are correctly
set:
```shell
$ geth init path/to/genesis.json
```
#### Creating the rendezvous point
With all nodes that you want to run initialized to the desired genesis state, you'll need to
start a bootstrap node that others can use to find each other in your network and/or over
the internet. The clean way is to configure and run a dedicated bootnode:
```shell
# Use the devp2p tool to create a node file.
# The devp2p tool is also part of the 'alltools' distribution bundle.
$ devp2p key generate node1.key
# file node1.key is created.
$ devp2p key to-enr -ip 10.2.3.4 -udp 30303 -tcp 30303 node1.key
# Prints the ENR for use in --bootnode flag of other nodes.
# Note this method requires knowing the IP/ports ahead of time.
$ geth --nodekey=node1.key
```
With the bootnode online, it will display an [`enode` URL](https://ethereum.org/en/developers/docs/networking-layer/network-addresses/#enode)
that other nodes can use to connect to it and exchange peer information. Make sure to
replace the displayed IP address information (most probably `[::]`) with your externally
accessible IP to get the actual `enode` URL.
*Note: You could previously use the `bootnode` utility to start a stripped down version of geth. This is not possible anymore.*
#### Starting up your member nodes
With the bootnode operational and externally reachable (you can try
`telnet <ip> <port>` to ensure it's indeed reachable), start every subsequent `geth`
node pointed to the bootnode for peer discovery via the `--bootnodes` flag. It will
probably also be desirable to keep the data directory of your private network separated, so
do also specify a custom `--datadir` flag.
```shell
$ geth --datadir=path/to/custom/data/folder --bootnodes=<bootnode-enode-url-from-above>
```
*Note: Since your network will be completely cut off from the main and test networks, you'll
also need to configure a miner to process transactions and create new blocks for you.*
#### Running a private miner
In a private network setting a single CPU miner instance is more than enough for
practical purposes as it can produce a stable stream of blocks at the correct intervals
without needing heavy resources (consider running on a single thread, no need for multiple
ones either). To start a `geth` instance for mining, run it with all your usual flags, extended
by:
```shell
$ geth <usual-flags> --mine --miner.threads=1 --miner.etherbase=0x0000000000000000000000000000000000000000
```
Which will start mining blocks and transactions on a single CPU thread, crediting all
proceedings to the account specified by `--miner.etherbase`. You can further tune the mining
by changing the default gas limit blocks converge to (`--miner.targetgaslimit`) and the price
transactions are accepted at (`--miner.gasprice`).
## Contribution ## Contribution

View file

@ -214,7 +214,9 @@ const (
// of starting any background processes such as automatic key derivation. // of starting any background processes such as automatic key derivation.
WalletOpened WalletOpened
// WalletDropped // WalletDropped is fired when a wallet is removed or disconnected, either via USB
// or due to a filesystem event in the keystore. This event indicates that the wallet
// is no longer available for operations.
WalletDropped WalletDropped
) )

View file

@ -56,37 +56,37 @@ fc77c0531406d092c5356167e45c05a22d16bea84e3fa555e0f03af085c11763 go1.23.4.windo
8347c1aa4e1e67954d12830f88dbe44bd7ac0ec134bb472783dbfb5a3a8865d0 go1.23.4.windows-arm64.msi 8347c1aa4e1e67954d12830f88dbe44bd7ac0ec134bb472783dbfb5a3a8865d0 go1.23.4.windows-arm64.msi
db69cae5006753c785345c3215ad941f8b6224e2f81fec471c42d6857bee0e6f go1.23.4.windows-arm64.zip db69cae5006753c785345c3215ad941f8b6224e2f81fec471c42d6857bee0e6f go1.23.4.windows-arm64.zip
# version:golangci 1.61.0 # version:golangci 1.63.4
# https://github.com/golangci/golangci-lint/releases/ # https://github.com/golangci/golangci-lint/releases/
# https://github.com/golangci/golangci-lint/releases/download/v1.61.0/ # https://github.com/golangci/golangci-lint/releases/download/v1.63.4/
5c280ef3284f80c54fd90d73dc39ca276953949da1db03eb9dd0fbf868cc6e55 golangci-lint-1.61.0-darwin-amd64.tar.gz 878d017cc360e4fb19510d39852c8189852e3c48e7ce0337577df73507c97d68 golangci-lint-1.63.4-darwin-amd64.tar.gz
544334890701e4e04a6e574bc010bea8945205c08c44cced73745a6378012d36 golangci-lint-1.61.0-darwin-arm64.tar.gz a2b630c2ac8466393f0ccbbede4462387b6c190697a70bc2298c6d2123f21bbf golangci-lint-1.63.4-darwin-arm64.tar.gz
e885a6f561092055930ebd298914d80e8fd2e10d2b1e9942836c2c6a115301fa golangci-lint-1.61.0-freebsd-386.tar.gz 8938b74aa92888e561a1c5a4c175110b92f84e7d24733703e6d9ebc39e9cd5f8 golangci-lint-1.63.4-freebsd-386.tar.gz
b13f6a3f11f65e7ff66b734d7554df3bbae0f485768848424e7554ed289e19c2 golangci-lint-1.61.0-freebsd-amd64.tar.gz 054903339d620df2e760b978920100986e3b03bcb058f669d520a71dac9c34ed golangci-lint-1.63.4-freebsd-amd64.tar.gz
cd8e7bbe5b8f33ed1597aa1cc588da96a3b9f22e1b9ae60d93511eae1a0ee8c5 golangci-lint-1.61.0-freebsd-armv6.tar.gz a19d499f961a02608348e8b626537a88edfaab6e1b6534f1eff742b5d6d750e4 golangci-lint-1.63.4-freebsd-armv6.tar.gz
7ade524dbd88bd250968f45e190af90e151fa5ee63dd6aa7f7bb90e8155db61d golangci-lint-1.61.0-freebsd-armv7.tar.gz 00d616f0fb275b780ce4d26604bdd7fdbfe6bc9c63acd5a0b31498e1f7511108 golangci-lint-1.63.4-freebsd-armv7.tar.gz
0fe3cd8a1ed8d9f54f48670a5af3df056d6040d94017057f0f4d65c930660ad9 golangci-lint-1.61.0-illumos-amd64.tar.gz d453688e0eabded3c1a97ff5a2777bb0df5a18851efdaaaf6b472e3e5713c33e golangci-lint-1.63.4-illumos-amd64.tar.gz
b463fc5053a612abd26393ebaff1d85d7d56058946f4f0f7bf25ed44ea899415 golangci-lint-1.61.0-linux-386.tar.gz 6b1bec847fc9f347d53712d05606a49d55d0e3b5c1bacadfed2393f3503de0e9 golangci-lint-1.63.4-linux-386.tar.gz
77cb0af99379d9a21d5dc8c38364d060e864a01bd2f3e30b5e8cc550c3a54111 golangci-lint-1.61.0-linux-amd64.tar.gz 01abb14a4df47b5ca585eff3c34b105023cba92ec34ff17212dbb83855581690 golangci-lint-1.63.4-linux-amd64.tar.gz
af60ac05566d9351615cb31b4cc070185c25bf8cbd9b09c1873aa5ec6f3cc17e golangci-lint-1.61.0-linux-arm64.tar.gz 51f0c79d19a92353e0465fb30a4901a0644a975d34e6f399ad2eebc0160bbb24 golangci-lint-1.63.4-linux-arm64.tar.gz
1f307f2fcc5d7d674062a967a0d83a7091e300529aa237ec6ad2b3dd14c897f5 golangci-lint-1.61.0-linux-armv6.tar.gz 8d0a43f41e8424fbae10f7aa2dc29999f98112817c6dba63d7dc76832940a673 golangci-lint-1.63.4-linux-armv6.tar.gz
3ad8cbaae75a547450844811300f99c4cd290277398e43d22b9eb1792d15af4c golangci-lint-1.61.0-linux-armv7.tar.gz 1045a047b31e9302c9160c7b0f199f4ac1bd02a1b221a2d9521bd3507f0cf671 golangci-lint-1.63.4-linux-armv7.tar.gz
9be2ca67d961d7699079739cf6f7c8291c5183d57e34d1677de21ca19d0bd3ed golangci-lint-1.61.0-linux-loong64.tar.gz 933fe10ab50ce3bb0806e15a4ae69fe20f0549abf91dea0161236000ca706e67 golangci-lint-1.63.4-linux-loong64.tar.gz
90d005e1648115ebf0861b408eab9c936079a24763e883058b0a227cd3135d31 golangci-lint-1.61.0-linux-mips64.tar.gz 45798630cbad5642862766051199fa862ef3c33d569cab12f01cac4f68e2ddd5 golangci-lint-1.63.4-linux-mips64.tar.gz
6d2ed4f49407115460b8c10ccfc40fd177e0887a48864a2879dd16e84ba2a48c golangci-lint-1.61.0-linux-mips64le.tar.gz 86ae25335ddb24975d2c915c1af0c7fad70dce99d0b4614fa4bee392de714aa2 golangci-lint-1.63.4-linux-mips64le.tar.gz
633089589af5a58b7430afb6eee107d4e9c99e8d91711ddc219eb13a07e8d3b8 golangci-lint-1.61.0-linux-ppc64le.tar.gz 33dabd11aaba4b602938da98bcf49aabab55019557e0115cdc3dbcc3009768fa golangci-lint-1.63.4-linux-ppc64le.tar.gz
4c1a097d9e0d1b4a8144dae6a1f5583a38d662f3bdc1498c4e954b6ed856be98 golangci-lint-1.61.0-linux-riscv64.tar.gz 4e7a81230a663bcdf30bba5689ce96040abc76994dbc2003dce32c8dca8c06f3 golangci-lint-1.63.4-linux-riscv64.tar.gz
30581d3c987d287b7064617f1a2694143e10dffc40bc25be6636006ee82d7e1c golangci-lint-1.61.0-linux-s390x.tar.gz 21370b49c7c47f4d9b8f982c952f940b01e65710174c3b4dad7b6452d58f92ec golangci-lint-1.63.4-linux-s390x.tar.gz
42530bf8100bd43c07f5efe6d92148ba6c5a7a712d510c6f24be85af6571d5eb golangci-lint-1.61.0-netbsd-386.tar.gz 255866a6464c7e11bb7edd8e6e6ad54f11e1f01b82ba9ca229698ac788cd9724 golangci-lint-1.63.4-netbsd-386.tar.gz
b8bb07c920f6601edf718d5e82ec0784fd590b0992b42b6ec18da99f26013ed4 golangci-lint-1.61.0-netbsd-amd64.tar.gz 2798c040ac658bda97224f204795199c81ac97bb207b21c02b664aaed380d5d2 golangci-lint-1.63.4-netbsd-amd64.tar.gz
353a51527c60bd0776b0891b03f247c791986f625fca689d121972c624e54198 golangci-lint-1.61.0-netbsd-arm64.tar.gz b910eecffd0064103837e7e1abe870deb8ade22331e6dffe319f430d49399c8e golangci-lint-1.63.4-netbsd-arm64.tar.gz
957a6272c3137910514225704c5dac0723b9c65eb7d9587366a997736e2d7580 golangci-lint-1.61.0-netbsd-armv6.tar.gz df2693ef37147b457c3e2089614537dd2ae2e18e53641e756a5b404f4c72d3fa golangci-lint-1.63.4-netbsd-armv6.tar.gz
a89eb28ff7f18f5cd52b914739360fa95cf2f643de4adeca46e26bec3a07e8d8 golangci-lint-1.61.0-netbsd-armv7.tar.gz a28a533366974bd7834c4516cd6075bff3419a508d1ed7aa63ae8182768b352e golangci-lint-1.63.4-netbsd-armv7.tar.gz
d8d74c43600b271393000717a4ed157d7a15bb85bab7db2efad9b63a694d4634 golangci-lint-1.61.0-windows-386.zip 368932775fb5c620b324dabf018155f3365f5e33c5af5b26e9321db373f96eea golangci-lint-1.63.4-windows-386.zip
e7bc2a81929a50f830244d6d2e657cce4f19a59aff49fa9000176ff34fda64ce golangci-lint-1.61.0-windows-amd64.zip 184d13c2b8f5441576bec2a0d8ba7b2d45445595cf796b879a73bcc98c39f8c1 golangci-lint-1.63.4-windows-amd64.zip
ed97c221596dd771e3dd9344872c140340bee2e819cd7a90afa1de752f1f2e0f golangci-lint-1.61.0-windows-arm64.zip 4fabf175d5b05ef0858ded49527948eebac50e9093814979fd84555a75fb80a6 golangci-lint-1.63.4-windows-arm64.zip
4b365233948b13d02d45928a5c390045e00945e919747b9887b5f260247541ae golangci-lint-1.61.0-windows-armv6.zip e92be3f3ff30d4a849fb4b9a4c8d56837dee45269cb405a3ecad52fa034c781b golangci-lint-1.63.4-windows-armv6.zip
595538fb64d152173959d28f6235227f9cd969a828e5af0c4e960d02af4ffd0e golangci-lint-1.61.0-windows-armv7.zip c71d348653b8f7fbb109bb10c1a481722bc6b0b2b6e731b897f99ac869f7653e golangci-lint-1.63.4-windows-armv7.zip
# This is the builder on PPA that will build Go itself (inception-y), don't modify! # This is the builder on PPA that will build Go itself (inception-y), don't modify!
# #

View file

@ -7,7 +7,7 @@ It enables usecases like the following:
* I want to auto-approve transactions with contract `CasinoDapp`, with up to `0.05 ether` in value to maximum `1 ether` per 24h period * I want to auto-approve transactions with contract `CasinoDapp`, with up to `0.05 ether` in value to maximum `1 ether` per 24h period
* I want to auto-approve transaction to contract `EthAlarmClock` with `data`=`0xdeadbeef`, if `value=0`, `gas < 44k` and `gasPrice < 40Gwei` * I want to auto-approve transaction to contract `EthAlarmClock` with `data`=`0xdeadbeef`, if `value=0`, `gas < 44k` and `gasPrice < 40Gwei`
The two main features that are required for this to work well are; The two main features that are required for this to work well are:
1. Rule Implementation: how to create, manage, and interpret rules in a flexible but secure manner 1. Rule Implementation: how to create, manage, and interpret rules in a flexible but secure manner
2. Credential management and credentials; how to provide auto-unlock without exposing keys unnecessarily. 2. Credential management and credentials; how to provide auto-unlock without exposing keys unnecessarily.
@ -29,10 +29,10 @@ function asBig(str) {
// Approve transactions to a certain contract if the value is below a certain limit // Approve transactions to a certain contract if the value is below a certain limit
function ApproveTx(req) { function ApproveTx(req) {
var limit = big.Newint("0xb1a2bc2ec50000") var limit = new BigNumber("0xb1a2bc2ec50000")
var value = asBig(req.transaction.value); var value = asBig(req.transaction.value);
if (req.transaction.to.toLowerCase() == "0xae967917c465db8578ca9024c205720b1a3651a9") && value.lt(limit)) { if (req.transaction.to.toLowerCase() == "0xae967917c465db8578ca9024c205720b1a3651a9" && value.lt(limit)) {
return "Approve" return "Approve"
} }
// If we return "Reject", it will be rejected. // If we return "Reject", it will be rejected.

View file

@ -28,7 +28,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"slices" "slices"
"sort"
"strings" "strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -41,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"golang.org/x/exp/maps"
) )
// Chain is a lightweight blockchain-like store which can read a hivechain // Chain is a lightweight blockchain-like store which can read a hivechain
@ -166,11 +166,8 @@ func (c *Chain) RootAt(height int) common.Hash {
// GetSender returns the address associated with account at the index in the // GetSender returns the address associated with account at the index in the
// pre-funded accounts list. // pre-funded accounts list.
func (c *Chain) GetSender(idx int) (common.Address, uint64) { func (c *Chain) GetSender(idx int) (common.Address, uint64) {
var accounts Addresses accounts := maps.Keys(c.senders)
for addr := range c.senders { slices.SortFunc(accounts, common.Address.Cmp)
accounts = append(accounts, addr)
}
sort.Sort(accounts)
addr := accounts[idx] addr := accounts[idx]
return addr, c.senders[addr].Nonce return addr, c.senders[addr].Nonce
} }
@ -260,22 +257,6 @@ func loadGenesis(genesisFile string) (core.Genesis, error) {
return gen, nil return gen, nil
} }
type Addresses []common.Address
func (a Addresses) Len() int {
return len(a)
}
func (a Addresses) Less(i, j int) bool {
return bytes.Compare(a[i][:], a[j][:]) < 0
}
func (a Addresses) Swap(i, j int) {
tmp := a[i]
a[i] = a[j]
a[j] = tmp
}
func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, error) { func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, error) {
// Load chain.rlp. // Load chain.rlp.
fh, err := os.Open(chainfile) fh, err := os.Open(chainfile)

View file

@ -13,6 +13,7 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package ethtest package ethtest
import ( import (

View file

@ -194,7 +194,7 @@ func PingExtraData(t *utesting.T) {
} }
} }
// This test sends a PING packet with additional data and wrong 'from' field // PingExtraDataWrongFrom sends a PING packet with additional data and wrong 'from' field
// and expects a PONG response. // and expects a PONG response.
func PingExtraDataWrongFrom(t *utesting.T) { func PingExtraDataWrongFrom(t *utesting.T) {
te := newTestEnv(Remote, Listen1, Listen2) te := newTestEnv(Remote, Listen1, Listen2)
@ -215,7 +215,7 @@ func PingExtraDataWrongFrom(t *utesting.T) {
} }
} }
// This test sends a PING packet with an expiration in the past. // PingPastExpiration sends a PING packet with an expiration in the past.
// The remote node should not respond. // The remote node should not respond.
func PingPastExpiration(t *utesting.T) { func PingPastExpiration(t *utesting.T) {
te := newTestEnv(Remote, Listen1, Listen2) te := newTestEnv(Remote, Listen1, Listen2)
@ -234,7 +234,7 @@ func PingPastExpiration(t *utesting.T) {
} }
} }
// This test sends an invalid packet. The remote node should not respond. // WrongPacketType sends an invalid packet. The remote node should not respond.
func WrongPacketType(t *utesting.T) { func WrongPacketType(t *utesting.T) {
te := newTestEnv(Remote, Listen1, Listen2) te := newTestEnv(Remote, Listen1, Listen2)
defer te.close() defer te.close()
@ -252,7 +252,7 @@ func WrongPacketType(t *utesting.T) {
} }
} }
// This test verifies that the default behaviour of ignoring 'from' fields is unaffected by // BondThenPingWithWrongFrom verifies that the default behaviour of ignoring 'from' fields is unaffected by
// the bonding process. After bonding, it pings the target with a different from endpoint. // the bonding process. After bonding, it pings the target with a different from endpoint.
func BondThenPingWithWrongFrom(t *utesting.T) { func BondThenPingWithWrongFrom(t *utesting.T) {
te := newTestEnv(Remote, Listen1, Listen2) te := newTestEnv(Remote, Listen1, Listen2)
@ -289,7 +289,7 @@ waitForPong:
} }
} }
// This test just sends FINDNODE. The remote node should not reply // FindnodeWithoutEndpointProof sends FINDNODE. The remote node should not reply
// because the endpoint proof has not completed. // because the endpoint proof has not completed.
func FindnodeWithoutEndpointProof(t *utesting.T) { func FindnodeWithoutEndpointProof(t *utesting.T) {
te := newTestEnv(Remote, Listen1, Listen2) te := newTestEnv(Remote, Listen1, Listen2)
@ -332,7 +332,7 @@ func BasicFindnode(t *utesting.T) {
} }
} }
// This test sends an unsolicited NEIGHBORS packet after the endpoint proof, then sends // UnsolicitedNeighbors sends an unsolicited NEIGHBORS packet after the endpoint proof, then sends
// FINDNODE to read the remote table. The remote node should not return the node contained // FINDNODE to read the remote table. The remote node should not return the node contained
// in the unsolicited NEIGHBORS packet. // in the unsolicited NEIGHBORS packet.
func UnsolicitedNeighbors(t *utesting.T) { func UnsolicitedNeighbors(t *utesting.T) {
@ -373,7 +373,7 @@ func UnsolicitedNeighbors(t *utesting.T) {
} }
} }
// This test sends FINDNODE with an expiration timestamp in the past. // FindnodePastExpiration sends FINDNODE with an expiration timestamp in the past.
// The remote node should not respond. // The remote node should not respond.
func FindnodePastExpiration(t *utesting.T) { func FindnodePastExpiration(t *utesting.T) {
te := newTestEnv(Remote, Listen1, Listen2) te := newTestEnv(Remote, Listen1, Listen2)
@ -426,7 +426,7 @@ func bond(t *utesting.T, te *testenv) {
} }
} }
// This test attempts to perform a traffic amplification attack against a // FindnodeAmplificationInvalidPongHash attempts to perform a traffic amplification attack against a
// 'victim' endpoint using FINDNODE. In this attack scenario, the attacker // 'victim' endpoint using FINDNODE. In this attack scenario, the attacker
// attempts to complete the endpoint proof non-interactively by sending a PONG // attempts to complete the endpoint proof non-interactively by sending a PONG
// with mismatching reply token from the 'victim' endpoint. The attack works if // with mismatching reply token from the 'victim' endpoint. The attack works if
@ -478,7 +478,7 @@ func FindnodeAmplificationInvalidPongHash(t *utesting.T) {
} }
} }
// This test attempts to perform a traffic amplification attack using FINDNODE. // FindnodeAmplificationWrongIP attempts to perform a traffic amplification attack using FINDNODE.
// The attack works if the remote node does not verify the IP address of FINDNODE // The attack works if the remote node does not verify the IP address of FINDNODE
// against the endpoint verification proof done by PING/PONG. // against the endpoint verification proof done by PING/PONG.
func FindnodeAmplificationWrongIP(t *utesting.T) { func FindnodeAmplificationWrongIP(t *utesting.T) {

View file

@ -230,11 +230,10 @@ func initGenesis(ctx *cli.Context) error {
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
defer triedb.Close() defer triedb.Close()
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides) _, hash, _, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
if err != nil { if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err) utils.Fatalf("Failed to write genesis block: %v", err)
} }
log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash) log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash)
return nil return nil

View file

@ -170,7 +170,7 @@ func TestHistoryImportAndExport(t *testing.T) {
db2.Close() db2.Close()
}) })
genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults)) genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults))
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil) imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
if err != nil { if err != nil {
t.Fatalf("unable to initialize chain: %v", err) t.Fatalf("unable to initialize chain: %v", err)

View file

@ -467,7 +467,6 @@ func (tt *cliqueTest) run(t *testing.T) {
for j := 0; j < len(batches)-1; j++ { for j := 0; j < len(batches)-1; j++ {
if k, err := chain.InsertChain(batches[j]); err != nil { if k, err := chain.InsertChain(batches[j]); err != nil {
t.Fatalf("failed to import batch %d, block %d: %v", j, k, err) t.Fatalf("failed to import batch %d, block %d: %v", j, k, err)
break
} }
} }
if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure { if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure {

View file

@ -269,14 +269,19 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
cacheConfig = defaultCacheConfig cacheConfig = defaultCacheConfig
} }
// Open trie database with provided config // Open trie database with provided config
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(genesis != nil && genesis.IsVerkle())) enableVerkle, err := EnableVerkleAtGenesis(db, genesis)
if err != nil {
return nil, err
}
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(enableVerkle))
// Setup the genesis block, commit the provided genesis specification // Write the supplied genesis to the database if it has not been initialized
// to database if the genesis block is not present yet, or load the // yet. The corresponding chain config will be returned, either from the
// stored one from database. // provided genesis or from the locally stored configuration if the genesis
chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) // has already been initialized.
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides)
return nil, genesisErr if err != nil {
return nil, err
} }
log.Info("") log.Info("")
log.Info(strings.Repeat("-", 153)) log.Info(strings.Repeat("-", 153))
@ -303,7 +308,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
vmConfig: vmConfig, vmConfig: vmConfig,
logger: vmConfig.Tracer, logger: vmConfig.Tracer,
} }
var err error
bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped) bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped)
if err != nil { if err != nil {
return nil, err return nil, err
@ -453,16 +457,15 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
} }
// Rewind the chain in case of an incompatible config upgrade. // Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok { if compatErr != nil {
log.Warn("Rewinding chain to upgrade configuration", "err", compat) log.Warn("Rewinding chain to upgrade configuration", "err", compatErr)
if compat.RewindToTime > 0 { if compatErr.RewindToTime > 0 {
bc.SetHeadWithTimestamp(compat.RewindToTime) bc.SetHeadWithTimestamp(compatErr.RewindToTime)
} else { } else {
bc.SetHead(compat.RewindToBlock) bc.SetHead(compatErr.RewindToBlock)
} }
rawdb.WriteChainConfig(db, genesisHash, chainConfig) rawdb.WriteChainConfig(db, genesisHash, chainConfig)
} }
// Start tx indexer if it's enabled. // Start tx indexer if it's enabled.
if txLookupLimit != nil { if txLookupLimit != nil {
bc.txIndexer = newTxIndexer(*txLookupLimit, bc) bc.txIndexer = newTxIndexer(*txLookupLimit, bc)

View file

@ -2535,7 +2535,7 @@ func testReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T, scheme strin
} }
// Benchmarks large blocks with value transfers to non-existing accounts // Benchmarks large blocks with value transfers to non-existing accounts
func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address) {
var ( var (
signer = types.HomesteadSigner{} signer = types.HomesteadSigner{}
testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@ -2598,10 +2598,7 @@ func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) {
recipientFn := func(nonce uint64) common.Address { recipientFn := func(nonce uint64) common.Address {
return common.BigToAddress(new(big.Int).SetUint64(1337 + nonce)) return common.BigToAddress(new(big.Int).SetUint64(1337 + nonce))
} }
dataFn := func(nonce uint64) []byte { benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn)
return nil
}
benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
} }
func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) {
@ -2615,10 +2612,7 @@ func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) {
recipientFn := func(nonce uint64) common.Address { recipientFn := func(nonce uint64) common.Address {
return common.BigToAddress(new(big.Int).SetUint64(1337)) return common.BigToAddress(new(big.Int).SetUint64(1337))
} }
dataFn := func(nonce uint64) []byte { benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn)
return nil
}
benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
} }
func BenchmarkBlockChain_1x1000Executions(b *testing.B) { func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
@ -2632,10 +2626,7 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
recipientFn := func(nonce uint64) common.Address { recipientFn := func(nonce uint64) common.Address {
return common.BigToAddress(new(big.Int).SetUint64(0xc0de)) return common.BigToAddress(new(big.Int).SetUint64(0xc0de))
} }
dataFn := func(nonce uint64) []byte { benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn)
return nil
}
benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
} }
// Tests that importing a some old blocks, where all blocks are before the // Tests that importing a some old blocks, where all blocks are before the
@ -4274,12 +4265,11 @@ func TestEIP7702(t *testing.T) {
// 2. addr1:0xaaaa calls into addr2:0xbbbb // 2. addr1:0xaaaa calls into addr2:0xbbbb
// 3. addr2:0xbbbb writes to storage // 3. addr2:0xbbbb writes to storage
auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{ auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{
ChainID: gspec.Config.ChainID.Uint64(), ChainID: *uint256.MustFromBig(gspec.Config.ChainID),
Address: aa, Address: aa,
Nonce: 1, Nonce: 1,
}) })
auth2, _ := types.SignSetCode(key2, types.SetCodeAuthorization{ auth2, _ := types.SignSetCode(key2, types.SetCodeAuthorization{
ChainID: 0,
Address: bb, Address: bb,
Nonce: 0, Nonce: 0,
}) })
@ -4287,7 +4277,7 @@ func TestEIP7702(t *testing.T) {
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
b.SetCoinbase(aa) b.SetCoinbase(aa)
txdata := &types.SetCodeTx{ txdata := &types.SetCodeTx{
ChainID: gspec.Config.ChainID.Uint64(), ChainID: uint256.MustFromBig(gspec.Config.ChainID),
Nonce: 0, Nonce: 0,
To: addr1, To: addr1,
Gas: 500000, Gas: 500000,

View file

@ -127,8 +127,12 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
} }
// Create an ephemeral in-memory database for computing hash, // Create an ephemeral in-memory database for computing hash,
// all the derived states will be discarded to not pollute disk. // all the derived states will be discarded to not pollute disk.
emptyRoot := types.EmptyRootHash
if isVerkle {
emptyRoot = types.EmptyVerkleHash
}
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb.NewDatabase(db, config), nil)) statedb, err := state.New(emptyRoot, state.NewDatabase(triedb.NewDatabase(db, config), nil))
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -148,7 +152,11 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
// flushAlloc is very similar with hash, but the main difference is all the // flushAlloc is very similar with hash, but the main difference is all the
// generated states will be persisted into the given database. // generated states will be persisted into the given database.
func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, error) { func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, error) {
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb, nil)) emptyRoot := types.EmptyRootHash
if triedb.IsVerkle() {
emptyRoot = types.EmptyVerkleHash
}
statedb, err := state.New(emptyRoot, state.NewDatabase(triedb, nil))
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -239,6 +247,24 @@ type ChainOverrides struct {
OverrideVerkle *uint64 OverrideVerkle *uint64
} }
// apply applies the chain overrides on the supplied chain config.
func (o *ChainOverrides) apply(cfg *params.ChainConfig) (*params.ChainConfig, error) {
if o == nil || cfg == nil {
return cfg, nil
}
cpy := *cfg
if o.OverrideCancun != nil {
cpy.CancunTime = o.OverrideCancun
}
if o.OverrideVerkle != nil {
cpy.VerkleTime = o.OverrideVerkle
}
if err := cpy.CheckConfigForkOrder(); err != nil {
return nil, err
}
return &cpy, nil
}
// SetupGenesisBlock writes or updates the genesis block in db. // SetupGenesisBlock writes or updates the genesis block in db.
// The block that will be used is: // The block that will be used is:
// //
@ -250,109 +276,102 @@ type ChainOverrides struct {
// The stored chain configuration will be updated if it is compatible (i.e. does not // The stored chain configuration will be updated if it is compatible (i.e. does not
// specify a fork block below the local head block). In case of a conflict, the // specify a fork block below the local head block). In case of a conflict, the
// error is a *params.ConfigCompatError and the new, unwritten config is returned. // error is a *params.ConfigCompatError and the new, unwritten config is returned.
// func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
// The returned chain configuration is never nil.
func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlockWithOverride(db, triedb, genesis, nil) return SetupGenesisBlockWithOverride(db, triedb, genesis, nil)
} }
func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, error) { func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
// Sanitize the supplied genesis, ensuring it has the associated chain
// config attached.
if genesis != nil && genesis.Config == nil { if genesis != nil && genesis.Config == nil {
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig return nil, common.Hash{}, nil, errGenesisNoConfig
} }
applyOverrides := func(config *params.ChainConfig) { // Commit the genesis if the database is empty
if config != nil { ghash := rawdb.ReadCanonicalHash(db, 0)
if overrides != nil && overrides.OverrideCancun != nil { if (ghash == common.Hash{}) {
config.CancunTime = overrides.OverrideCancun
}
if overrides != nil && overrides.OverrideVerkle != nil {
config.VerkleTime = overrides.OverrideVerkle
}
}
}
// Just commit the new block if there is no stored genesis block.
stored := rawdb.ReadCanonicalHash(db, 0)
if (stored == common.Hash{}) {
if genesis == nil { if genesis == nil {
log.Info("Writing default main-net genesis block") log.Info("Writing default main-net genesis block")
genesis = DefaultGenesisBlock() genesis = DefaultGenesisBlock()
} else { } else {
log.Info("Writing custom genesis block") log.Info("Writing custom genesis block")
} }
chainCfg, err := overrides.apply(genesis.Config)
if err != nil {
return nil, common.Hash{}, nil, err
}
genesis.Config = chainCfg
applyOverrides(genesis.Config)
block, err := genesis.Commit(db, triedb) block, err := genesis.Commit(db, triedb)
if err != nil { if err != nil {
return genesis.Config, common.Hash{}, err return nil, common.Hash{}, nil, err
} }
return genesis.Config, block.Hash(), nil return chainCfg, block.Hash(), nil, nil
} }
// The genesis block is present(perhaps in ancient database) while the // Commit the genesis if the genesis block exists in the ancient database
// state database is not initialized yet. It can happen that the node // but the key-value database is empty without initializing the genesis
// is initialized with an external ancient store. Commit genesis state // fields. This scenario can occur when the node is created from scratch
// in this case. // with an existing ancient store.
header := rawdb.ReadHeader(db, stored, 0) storedCfg := rawdb.ReadChainConfig(db, ghash)
if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) { if storedCfg == nil {
// Ensure the stored genesis block matches with the given genesis. Private
// networks must explicitly specify the genesis in the config file, mainnet
// genesis will be used as default and the initialization will always fail.
if genesis == nil { if genesis == nil {
log.Info("Writing default main-net genesis block")
genesis = DefaultGenesisBlock() genesis = DefaultGenesisBlock()
} else {
log.Info("Writing custom genesis block")
} }
applyOverrides(genesis.Config) chainCfg, err := overrides.apply(genesis.Config)
// Ensure the stored genesis matches with the given one. if err != nil {
hash := genesis.ToBlock().Hash() return nil, common.Hash{}, nil, err
if hash != stored { }
return genesis.Config, hash, &GenesisMismatchError{stored, hash} genesis.Config = chainCfg
if hash := genesis.ToBlock().Hash(); hash != ghash {
return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash}
} }
block, err := genesis.Commit(db, triedb) block, err := genesis.Commit(db, triedb)
if err != nil { if err != nil {
return genesis.Config, hash, err return nil, common.Hash{}, nil, err
} }
return genesis.Config, block.Hash(), nil return chainCfg, block.Hash(), nil, nil
} }
// Check whether the genesis block is already written. // The genesis block has already been committed previously. Verify that the
// provided genesis with chain overrides matches the existing one, and update
// the stored chain config if necessary.
if genesis != nil { if genesis != nil {
applyOverrides(genesis.Config) chainCfg, err := overrides.apply(genesis.Config)
hash := genesis.ToBlock().Hash() if err != nil {
if hash != stored { return nil, common.Hash{}, nil, err
return genesis.Config, hash, &GenesisMismatchError{stored, hash}
} }
genesis.Config = chainCfg
if hash := genesis.ToBlock().Hash(); hash != ghash {
return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash}
} }
// Get the existing chain configuration.
newcfg := genesis.configOrDefault(stored)
applyOverrides(newcfg)
if err := newcfg.CheckConfigForkOrder(); err != nil {
return newcfg, common.Hash{}, err
}
storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg == nil {
log.Warn("Found genesis block without chain config")
rawdb.WriteChainConfig(db, stored, newcfg)
return newcfg, stored, nil
}
storedData, _ := json.Marshal(storedcfg)
// Special case: if a private network is being used (no genesis and also no
// mainnet hash in the database), we must not apply the `configOrDefault`
// chain config as that would be AllProtocolChanges (applying any new fork
// on top of an existing private network genesis block). In that case, only
// apply the overrides.
if genesis == nil && stored != params.MainnetGenesisHash {
newcfg = storedcfg
applyOverrides(newcfg)
} }
// Check config compatibility and write the config. Compatibility errors // Check config compatibility and write the config. Compatibility errors
// are returned to the caller unless we're already at block zero. // are returned to the caller unless we're already at block zero.
head := rawdb.ReadHeadHeader(db) head := rawdb.ReadHeadHeader(db)
if head == nil { if head == nil {
return newcfg, stored, errors.New("missing head header") return nil, common.Hash{}, nil, errors.New("missing head header")
} }
compatErr := storedcfg.CheckCompatible(newcfg, head.Number.Uint64(), head.Time) newCfg := genesis.chainConfigOrDefault(ghash, storedCfg)
// TODO(rjl493456442) better to define the comparator of chain config
// and short circuit if the chain config is not changed.
compatErr := storedCfg.CheckCompatible(newCfg, head.Number.Uint64(), head.Time)
if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) { if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) {
return newcfg, stored, compatErr return newCfg, ghash, compatErr, nil
} }
// Don't overwrite if the old is identical to the new // Don't overwrite if the old is identical to the new. It's useful
if newData, _ := json.Marshal(newcfg); !bytes.Equal(storedData, newData) { // for the scenarios that database is opened in the read-only mode.
rawdb.WriteChainConfig(db, stored, newcfg) storedData, _ := json.Marshal(storedCfg)
if newData, _ := json.Marshal(newCfg); !bytes.Equal(storedData, newData) {
rawdb.WriteChainConfig(db, ghash, newCfg)
} }
return newcfg, stored, nil return newCfg, ghash, nil, nil
} }
// LoadChainConfig loads the stored chain config if it is already present in // LoadChainConfig loads the stored chain config if it is already present in
@ -388,7 +407,10 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig,
return params.MainnetChainConfig, nil return params.MainnetChainConfig, nil
} }
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { // chainConfigOrDefault retrieves the attached chain configuration. If the genesis
// object is null, it returns the default chain configuration based on the given
// genesis hash, or the locally stored config if it's not a pre-defined network.
func (g *Genesis) chainConfigOrDefault(ghash common.Hash, stored *params.ChainConfig) *params.ChainConfig {
switch { switch {
case g != nil: case g != nil:
return g.Config return g.Config
@ -399,14 +421,14 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
case ghash == params.SepoliaGenesisHash: case ghash == params.SepoliaGenesisHash:
return params.SepoliaChainConfig return params.SepoliaChainConfig
default: default:
return params.AllEthashProtocolChanges return stored
} }
} }
// IsVerkle indicates whether the state is already stored in a verkle // IsVerkle indicates whether the state is already stored in a verkle
// tree at genesis time. // tree at genesis time.
func (g *Genesis) IsVerkle() bool { func (g *Genesis) IsVerkle() bool {
return g.Config.IsVerkle(new(big.Int).SetUint64(g.Number), g.Timestamp) return g.Config.IsVerkleGenesis()
} }
// ToBlock returns the genesis block according to genesis specification. // ToBlock returns the genesis block according to genesis specification.
@ -486,7 +508,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
} }
config := g.Config config := g.Config
if config == nil { if config == nil {
config = params.AllEthashProtocolChanges return nil, errors.New("invalid genesis without chain config")
} }
if err := config.CheckConfigForkOrder(); err != nil { if err := config.CheckConfigForkOrder(); err != nil {
return nil, err return nil, err
@ -506,16 +528,17 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
if err != nil { if err != nil {
return nil, err return nil, err
} }
rawdb.WriteGenesisStateSpec(db, block.Hash(), blob) batch := db.NewBatch()
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) rawdb.WriteGenesisStateSpec(batch, block.Hash(), blob)
rawdb.WriteBlock(db, block) rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), block.Difficulty())
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) rawdb.WriteBlock(batch, block)
rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), nil)
rawdb.WriteHeadBlockHash(db, block.Hash()) rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
rawdb.WriteHeadFastBlockHash(db, block.Hash()) rawdb.WriteHeadBlockHash(batch, block.Hash())
rawdb.WriteHeadHeaderHash(db, block.Hash()) rawdb.WriteHeadFastBlockHash(batch, block.Hash())
rawdb.WriteChainConfig(db, block.Hash(), config) rawdb.WriteHeadHeaderHash(batch, block.Hash())
return block, nil rawdb.WriteChainConfig(batch, block.Hash(), config)
return block, batch.Write()
} }
// MustCommit writes the genesis block and state to db, panicking on error. // MustCommit writes the genesis block and state to db, panicking on error.
@ -528,6 +551,29 @@ func (g *Genesis) MustCommit(db ethdb.Database, triedb *triedb.Database) *types.
return block return block
} }
// EnableVerkleAtGenesis indicates whether the verkle fork should be activated
// at genesis. This is a temporary solution only for verkle devnet testing, where
// verkle fork is activated at genesis, and the configured activation date has
// already passed.
//
// In production networks (mainnet and public testnets), verkle activation always
// occurs after the genesis block, making this function irrelevant in those cases.
func EnableVerkleAtGenesis(db ethdb.Database, genesis *Genesis) (bool, error) {
if genesis != nil {
if genesis.Config == nil {
return false, errGenesisNoConfig
}
return genesis.Config.EnableVerkleAtGenesis, nil
}
if ghash := rawdb.ReadCanonicalHash(db, 0); ghash != (common.Hash{}) {
chainCfg := rawdb.ReadChainConfig(db, ghash)
if chainCfg != nil {
return chainCfg.EnableVerkleAtGenesis, nil
}
}
return false, nil
}
// DefaultGenesisBlock returns the Ethereum main net genesis block. // DefaultGenesisBlock returns the Ethereum main net genesis block.
func DefaultGenesisBlock() *Genesis { func DefaultGenesisBlock() *Genesis {
return &Genesis{ return &Genesis{

View file

@ -55,22 +55,22 @@ func testSetupGenesis(t *testing.T, scheme string) {
tests := []struct { tests := []struct {
name string name string
fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error) fn func(ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error)
wantConfig *params.ChainConfig wantConfig *params.ChainConfig
wantHash common.Hash wantHash common.Hash
wantErr error wantErr error
wantCompactErr *params.ConfigCompatError
}{ }{
{ {
name: "genesis without ChainConfig", name: "genesis without ChainConfig",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), new(Genesis)) return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), new(Genesis))
}, },
wantErr: errGenesisNoConfig, wantErr: errGenesisNoConfig,
wantConfig: params.AllEthashProtocolChanges,
}, },
{ {
name: "no block in DB, genesis == nil", name: "no block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
}, },
wantHash: params.MainnetGenesisHash, wantHash: params.MainnetGenesisHash,
@ -78,7 +78,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
}, },
{ {
name: "mainnet block in DB, genesis == nil", name: "mainnet block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme))) DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme)))
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
}, },
@ -87,7 +87,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
}, },
{ {
name: "custom block in DB, genesis == nil", name: "custom block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb) customg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, nil) return SetupGenesisBlock(db, tdb, nil)
@ -97,18 +97,16 @@ func testSetupGenesis(t *testing.T, scheme string) {
}, },
{ {
name: "custom block in DB, genesis == sepolia", name: "custom block in DB, genesis == sepolia",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb) customg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, DefaultSepoliaGenesisBlock()) return SetupGenesisBlock(db, tdb, DefaultSepoliaGenesisBlock())
}, },
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash}, wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
wantHash: params.SepoliaGenesisHash,
wantConfig: params.SepoliaChainConfig,
}, },
{ {
name: "compatible config in DB", name: "compatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb) oldcustomg.Commit(db, tdb)
return SetupGenesisBlock(db, tdb, &customg) return SetupGenesisBlock(db, tdb, &customg)
@ -118,7 +116,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
}, },
{ {
name: "incompatible config in DB", name: "incompatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
// Commit the 'old' genesis block with Homestead transition at #2. // Commit the 'old' genesis block with Homestead transition at #2.
// Advance to block #4, past the homestead transition block of customg. // Advance to block #4, past the homestead transition block of customg.
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
@ -135,7 +133,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
}, },
wantHash: customghash, wantHash: customghash,
wantConfig: customg.Config, wantConfig: customg.Config,
wantErr: &params.ConfigCompatError{ wantCompactErr: &params.ConfigCompatError{
What: "Homestead fork block", What: "Homestead fork block",
StoredBlock: big.NewInt(2), StoredBlock: big.NewInt(2),
NewBlock: big.NewInt(3), NewBlock: big.NewInt(3),
@ -146,12 +144,16 @@ func testSetupGenesis(t *testing.T, scheme string) {
for _, test := range tests { for _, test := range tests {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
config, hash, err := test.fn(db) config, hash, compatErr, err := test.fn(db)
// Check the return values. // Check the return values.
if !reflect.DeepEqual(err, test.wantErr) { if !reflect.DeepEqual(err, test.wantErr) {
spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true} spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr)) t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
} }
if !reflect.DeepEqual(compatErr, test.wantCompactErr) {
spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(compatErr), spew.NewFormatter(test.wantCompactErr))
}
if !reflect.DeepEqual(config, test.wantConfig) { if !reflect.DeepEqual(config, test.wantConfig) {
t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig) t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig)
} }
@ -279,6 +281,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
PragueTime: &verkleTime, PragueTime: &verkleTime,
VerkleTime: &verkleTime, VerkleTime: &verkleTime,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
EnableVerkleAtGenesis: true,
Ethash: nil, Ethash: nil,
Clique: nil, Clique: nil,
} }

View file

@ -87,6 +87,10 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
) )
// Ensure the datadir is not a symbolic link if it exists. // Ensure the datadir is not a symbolic link if it exists.
if info, err := os.Lstat(datadir); !os.IsNotExist(err) { if info, err := os.Lstat(datadir); !os.IsNotExist(err) {
if info == nil {
log.Warn("Could not Lstat the database", "path", datadir)
return nil, errors.New("lstat failed")
}
if info.Mode()&os.ModeSymlink != 0 { if info.Mode()&os.ModeSymlink != 0 {
log.Warn("Symbolic link ancient database is not supported", "path", datadir) log.Warn("Symbolic link ancient database is not supported", "path", datadir)
return nil, errSymlinkDatadir return nil, errSymlinkDatadir

View file

@ -20,7 +20,6 @@ import (
"maps" "maps"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
) )
@ -133,8 +132,8 @@ func newStateUpdate(originRoot common.Hash, root common.Hash, deletes map[common
} }
} }
return &stateUpdate{ return &stateUpdate{
originRoot: types.TrieRootHash(originRoot), originRoot: originRoot,
root: types.TrieRootHash(root), root: root,
accounts: accounts, accounts: accounts,
accountsOrigin: accountsOrigin, accountsOrigin: accountsOrigin,
storages: storages, storages: storages,

View file

@ -470,7 +470,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
if msg.SetCodeAuthorizations != nil { if msg.SetCodeAuthorizations != nil {
for _, auth := range msg.SetCodeAuthorizations { for _, auth := range msg.SetCodeAuthorizations {
// Note errors are ignored, we simply skip invalid authorizations here. // Note errors are ignored, we simply skip invalid authorizations here.
st.applyAuthorization(msg, &auth) st.applyAuthorization(&auth)
} }
} }
@ -529,8 +529,8 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
// validateAuthorization validates an EIP-7702 authorization against the state. // validateAuthorization validates an EIP-7702 authorization against the state.
func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorization) (authority common.Address, err error) { func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorization) (authority common.Address, err error) {
// Verify chain ID is 0 or equal to current chain ID. // Verify chain ID is null or equal to current chain ID.
if auth.ChainID != 0 && st.evm.ChainConfig().ChainID.Uint64() != auth.ChainID { if !auth.ChainID.IsZero() && auth.ChainID.CmpBig(st.evm.ChainConfig().ChainID) != 0 {
return authority, ErrAuthorizationWrongChainID return authority, ErrAuthorizationWrongChainID
} }
// Limit nonce to 2^64-1 per EIP-2681. // Limit nonce to 2^64-1 per EIP-2681.
@ -559,7 +559,7 @@ func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorizatio
} }
// applyAuthorization applies an EIP-7702 code delegation to the state. // applyAuthorization applies an EIP-7702 code delegation to the state.
func (st *stateTransition) applyAuthorization(msg *Message, auth *types.SetCodeAuthorization) error { func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization) error {
authority, err := st.validateAuthorization(auth) authority, err := st.validateAuthorization(auth)
if err != nil { if err != nil {
return err return err

View file

@ -293,7 +293,7 @@ const (
GasChangeCallLeftOverRefunded GasChangeReason = 7 GasChangeCallLeftOverRefunded GasChangeReason = 7
// GasChangeCallContractCreation is the amount of gas that will be burned for a CREATE. // GasChangeCallContractCreation is the amount of gas that will be burned for a CREATE.
GasChangeCallContractCreation GasChangeReason = 8 GasChangeCallContractCreation GasChangeReason = 8
// GasChangeContractCreation is the amount of gas that will be burned for a CREATE2. // GasChangeCallContractCreation2 is the amount of gas that will be burned for a CREATE2.
GasChangeCallContractCreation2 GasChangeReason = 9 GasChangeCallContractCreation2 GasChangeReason = 9
// GasChangeCallCodeStorage is the amount of gas that will be charged for code storage. // GasChangeCallCodeStorage is the amount of gas that will be charged for code storage.
GasChangeCallCodeStorage GasChangeReason = 10 GasChangeCallCodeStorage GasChangeReason = 10

View file

@ -1751,7 +1751,7 @@ func (p *BlobPool) Clear() {
// The transaction addition may attempt to reserve the sender addr which // The transaction addition may attempt to reserve the sender addr which
// can't happen until Clear releases the reservation lock. Clear cannot // can't happen until Clear releases the reservation lock. Clear cannot
// acquire the subpool lock until the transaction addition is completed. // acquire the subpool lock until the transaction addition is completed.
for acct, _ := range p.index { for acct := range p.index {
p.reserve(acct, false) p.reserve(acct, false)
} }
p.lookup = newLookup() p.lookup = newLookup()

View file

@ -1986,7 +1986,7 @@ func (pool *LegacyPool) Clear() {
senderAddr, _ := types.Sender(pool.signer, tx) senderAddr, _ := types.Sender(pool.signer, tx)
pool.reserve(senderAddr, false) pool.reserve(senderAddr, false)
} }
for localSender, _ := range pool.locals.accounts { for localSender := range pool.locals.accounts {
pool.reserve(localSender, false) pool.reserve(localSender, false)
} }

View file

@ -162,12 +162,12 @@ func TestTransactionZAttack(t *testing.T) {
var ivpendingNum int var ivpendingNum int
pendingtxs, _ := pool.Content() pendingtxs, _ := pool.Content()
for account, txs := range pendingtxs { for account, txs := range pendingtxs {
cur_balance := new(big.Int).Set(pool.currentState.GetBalance(account).ToBig()) curBalance := new(big.Int).Set(pool.currentState.GetBalance(account).ToBig())
for _, tx := range txs { for _, tx := range txs {
if cur_balance.Cmp(tx.Value()) <= 0 { if curBalance.Cmp(tx.Value()) <= 0 {
ivpendingNum++ ivpendingNum++
} else { } else {
cur_balance.Sub(cur_balance, tx.Value()) curBalance.Sub(curBalance, tx.Value())
} }
} }
} }

View file

@ -1243,33 +1243,28 @@ func TestAllowedTxSize(t *testing.T) {
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
testAddBalance(pool, account, big.NewInt(1000000000)) testAddBalance(pool, account, big.NewInt(1000000000))
// Compute maximal data size for transactions (lower bound). // Find the maximum data length for the kind of transaction which will
// // be generated in the pool.addRemoteSync calls below.
// It is assumed the fields in the transaction (except of the data) are: const largeDataLength = txMaxSize - 200 // enough to have a 5 bytes RLP encoding of the data length number
// - nonce <= 32 bytes txWithLargeData := pricedDataTransaction(0, pool.currentHead.Load().GasLimit, big.NewInt(1), key, largeDataLength)
// - gasTip <= 32 bytes maxTxLengthWithoutData := txWithLargeData.Size() - largeDataLength // 103 bytes
// - gasLimit <= 32 bytes maxTxDataLength := txMaxSize - maxTxLengthWithoutData // 131072 - 103 = 130953 bytes
// - recipient == 20 bytes
// - value <= 32 bytes
// - signature == 65 bytes
// All those fields are summed up to at most 213 bytes.
baseSize := uint64(213)
dataSize := txMaxSize - baseSize
// Try adding a transaction with maximal allowed size // Try adding a transaction with maximal allowed size
tx := pricedDataTransaction(0, pool.currentHead.Load().GasLimit, big.NewInt(1), key, dataSize) tx := pricedDataTransaction(0, pool.currentHead.Load().GasLimit, big.NewInt(1), key, maxTxDataLength)
if err := pool.addRemoteSync(tx); err != nil { if err := pool.addRemoteSync(tx); err != nil {
t.Fatalf("failed to add transaction of size %d, close to maximal: %v", int(tx.Size()), err) t.Fatalf("failed to add transaction of size %d, close to maximal: %v", int(tx.Size()), err)
} }
// Try adding a transaction with random allowed size // Try adding a transaction with random allowed size
if err := pool.addRemoteSync(pricedDataTransaction(1, pool.currentHead.Load().GasLimit, big.NewInt(1), key, uint64(rand.Intn(int(dataSize))))); err != nil { if err := pool.addRemoteSync(pricedDataTransaction(1, pool.currentHead.Load().GasLimit, big.NewInt(1), key, uint64(rand.Intn(int(maxTxDataLength+1))))); err != nil {
t.Fatalf("failed to add transaction of random allowed size: %v", err) t.Fatalf("failed to add transaction of random allowed size: %v", err)
} }
// Try adding a transaction of minimal not allowed size // Try adding a transaction above maximum size by one
if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentHead.Load().GasLimit, big.NewInt(1), key, txMaxSize)); err == nil { if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentHead.Load().GasLimit, big.NewInt(1), key, maxTxDataLength+1)); err == nil {
t.Fatalf("expected rejection on slightly oversize transaction") t.Fatalf("expected rejection on slightly oversize transaction")
} }
// Try adding a transaction of random not allowed size // Try adding a transaction above maximum size by more than one
if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentHead.Load().GasLimit, big.NewInt(1), key, dataSize+1+uint64(rand.Intn(10*txMaxSize)))); err == nil { if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentHead.Load().GasLimit, big.NewInt(1), key, maxTxDataLength+1+uint64(rand.Intn(10*txMaxSize)))); err == nil {
t.Fatalf("expected rejection on oversize transaction") t.Fatalf("expected rejection on oversize transaction")
} }
// Run some sanity checks on the pool internals // Run some sanity checks on the pool internals

View file

@ -24,7 +24,7 @@ const (
depositRequestSize = 192 depositRequestSize = 192
) )
// UnpackIntoDeposit unpacks a serialized DepositEvent. // DepositLogToRequest unpacks a serialized DepositEvent.
func DepositLogToRequest(data []byte) ([]byte, error) { func DepositLogToRequest(data []byte) ([]byte, error) {
if len(data) != 576 { if len(data) != 576 {
return nil, fmt.Errorf("deposit wrong length: want 576, have %d", len(data)) return nil, fmt.Errorf("deposit wrong length: want 576, have %d", len(data))

View file

@ -16,7 +16,7 @@ var _ = (*authorizationMarshaling)(nil)
// MarshalJSON marshals as JSON. // MarshalJSON marshals as JSON.
func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) { func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
type SetCodeAuthorization struct { type SetCodeAuthorization struct {
ChainID hexutil.Uint64 `json:"chainId" gencodec:"required"` ChainID hexutil.U256 `json:"chainId" gencodec:"required"`
Address common.Address `json:"address" gencodec:"required"` Address common.Address `json:"address" gencodec:"required"`
Nonce hexutil.Uint64 `json:"nonce" gencodec:"required"` Nonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
V hexutil.Uint64 `json:"yParity" gencodec:"required"` V hexutil.Uint64 `json:"yParity" gencodec:"required"`
@ -24,7 +24,7 @@ func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
S hexutil.U256 `json:"s" gencodec:"required"` S hexutil.U256 `json:"s" gencodec:"required"`
} }
var enc SetCodeAuthorization var enc SetCodeAuthorization
enc.ChainID = hexutil.Uint64(s.ChainID) enc.ChainID = hexutil.U256(s.ChainID)
enc.Address = s.Address enc.Address = s.Address
enc.Nonce = hexutil.Uint64(s.Nonce) enc.Nonce = hexutil.Uint64(s.Nonce)
enc.V = hexutil.Uint64(s.V) enc.V = hexutil.Uint64(s.V)
@ -36,7 +36,7 @@ func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON. // UnmarshalJSON unmarshals from JSON.
func (s *SetCodeAuthorization) UnmarshalJSON(input []byte) error { func (s *SetCodeAuthorization) UnmarshalJSON(input []byte) error {
type SetCodeAuthorization struct { type SetCodeAuthorization struct {
ChainID *hexutil.Uint64 `json:"chainId" gencodec:"required"` ChainID *hexutil.U256 `json:"chainId" gencodec:"required"`
Address *common.Address `json:"address" gencodec:"required"` Address *common.Address `json:"address" gencodec:"required"`
Nonce *hexutil.Uint64 `json:"nonce" gencodec:"required"` Nonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
V *hexutil.Uint64 `json:"yParity" gencodec:"required"` V *hexutil.Uint64 `json:"yParity" gencodec:"required"`
@ -50,7 +50,7 @@ func (s *SetCodeAuthorization) UnmarshalJSON(input []byte) error {
if dec.ChainID == nil { if dec.ChainID == nil {
return errors.New("missing required field 'chainId' for SetCodeAuthorization") return errors.New("missing required field 'chainId' for SetCodeAuthorization")
} }
s.ChainID = uint64(*dec.ChainID) s.ChainID = uint256.Int(*dec.ChainID)
if dec.Address == nil { if dec.Address == nil {
return errors.New("missing required field 'address' for SetCodeAuthorization") return errors.New("missing required field 'address' for SetCodeAuthorization")
} }

View file

@ -19,7 +19,6 @@ package types
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
) )
var ( var (
@ -47,13 +46,3 @@ var (
// EmptyVerkleHash is the known hash of an empty verkle trie. // EmptyVerkleHash is the known hash of an empty verkle trie.
EmptyVerkleHash = common.Hash{} EmptyVerkleHash = common.Hash{}
) )
// TrieRootHash returns the hash itself if it's non-empty or the predefined
// emptyHash one instead.
func TrieRootHash(hash common.Hash) common.Hash {
if hash == (common.Hash{}) {
log.Error("Zero trie root hash!")
return EmptyRootHash
}
return hash
}

View file

@ -111,7 +111,7 @@ func TestFuzzDeriveSha(t *testing.T) {
exp := types.DeriveSha(newDummy(i), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))) exp := types.DeriveSha(newDummy(i), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
got := types.DeriveSha(newDummy(i), trie.NewStackTrie(nil)) got := types.DeriveSha(newDummy(i), trie.NewStackTrie(nil))
if !bytes.Equal(got[:], exp[:]) { if !bytes.Equal(got[:], exp[:]) {
printList(newDummy(seed)) printList(t, newDummy(seed))
t.Fatalf("seed %d: got %x exp %x", seed, got, exp) t.Fatalf("seed %d: got %x exp %x", seed, got, exp)
} }
} }
@ -192,15 +192,21 @@ func (d *dummyDerivableList) EncodeIndex(i int, w *bytes.Buffer) {
io.CopyN(w, mrand.New(src), size) io.CopyN(w, mrand.New(src), size)
} }
func printList(l types.DerivableList) { func printList(t *testing.T, l types.DerivableList) {
fmt.Printf("list length: %d\n", l.Len())
fmt.Printf("{\n")
for i := 0; i < l.Len(); i++ {
var buf bytes.Buffer var buf bytes.Buffer
l.EncodeIndex(i, &buf) _, _ = fmt.Fprintf(&buf, "list length: %d, ", l.Len())
fmt.Printf("\"%#x\",\n", buf.Bytes()) buf.WriteString("list: [")
for i := 0; i < l.Len(); i++ {
var itemBuf bytes.Buffer
l.EncodeIndex(i, &itemBuf)
if i == l.Len()-1 {
_, _ = fmt.Fprintf(&buf, "\"%#x\"", itemBuf.Bytes())
} else {
_, _ = fmt.Fprintf(&buf, "\"%#x\",", itemBuf.Bytes())
} }
fmt.Printf("},\n") }
buf.WriteString("]")
t.Log(buf.String())
} }
type flatList []string type flatList []string

View file

@ -155,7 +155,7 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
enc.Proofs = itx.Sidecar.Proofs enc.Proofs = itx.Sidecar.Proofs
} }
case *SetCodeTx: case *SetCodeTx:
enc.ChainID = (*hexutil.Big)(new(big.Int).SetUint64(itx.ChainID)) enc.ChainID = (*hexutil.Big)(itx.ChainID.ToBig())
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
enc.To = tx.To() enc.To = tx.To()
enc.Gas = (*hexutil.Uint64)(&itx.Gas) enc.Gas = (*hexutil.Uint64)(&itx.Gas)
@ -353,7 +353,11 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
if dec.ChainID == nil { if dec.ChainID == nil {
return errors.New("missing required field 'chainId' in transaction") return errors.New("missing required field 'chainId' in transaction")
} }
itx.ChainID = uint256.MustFromBig((*big.Int)(dec.ChainID)) var overflow bool
itx.ChainID, overflow = uint256.FromBig(dec.ChainID.ToInt())
if overflow {
return errors.New("'chainId' value overflows uint256")
}
if dec.Nonce == nil { if dec.Nonce == nil {
return errors.New("missing required field 'nonce' in transaction") return errors.New("missing required field 'nonce' in transaction")
} }
@ -395,7 +399,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
itx.BlobHashes = dec.BlobVersionedHashes itx.BlobHashes = dec.BlobVersionedHashes
// signature R // signature R
var overflow bool
if dec.R == nil { if dec.R == nil {
return errors.New("missing required field 'r' in transaction") return errors.New("missing required field 'r' in transaction")
} }
@ -432,7 +435,11 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
if dec.ChainID == nil { if dec.ChainID == nil {
return errors.New("missing required field 'chainId' in transaction") return errors.New("missing required field 'chainId' in transaction")
} }
itx.ChainID = dec.ChainID.ToInt().Uint64() var overflow bool
itx.ChainID, overflow = uint256.FromBig(dec.ChainID.ToInt())
if overflow {
return errors.New("'chainId' value overflows uint256")
}
if dec.Nonce == nil { if dec.Nonce == nil {
return errors.New("missing required field 'nonce' in transaction") return errors.New("missing required field 'nonce' in transaction")
} }
@ -470,7 +477,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
itx.AuthList = dec.AuthorizationList itx.AuthList = dec.AuthorizationList
// signature R // signature R
var overflow bool
if dec.R == nil { if dec.R == nil {
return errors.New("missing required field 'r' in transaction") return errors.New("missing required field 'r' in transaction")
} }

View file

@ -219,7 +219,7 @@ func (s pragueSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big
} }
// Check that chain ID of tx matches the signer. We also accept ID zero here, // Check that chain ID of tx matches the signer. We also accept ID zero here,
// because it indicates that the chain ID was not specified in the tx. // because it indicates that the chain ID was not specified in the tx.
if txdata.ChainID != 0 && new(big.Int).SetUint64(txdata.ChainID).Cmp(s.chainId) != 0 { if txdata.ChainID != nil && txdata.ChainID.CmpBig(s.chainId) != 0 {
return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId)
} }
R, S, _ = decodeSignature(sig) R, S, _ = decodeSignature(sig)

View file

@ -47,9 +47,9 @@ type BlobTx struct {
Sidecar *BlobTxSidecar `rlp:"-"` Sidecar *BlobTxSidecar `rlp:"-"`
// Signature values // Signature values
V *uint256.Int `json:"v" gencodec:"required"` V *uint256.Int
R *uint256.Int `json:"r" gencodec:"required"` R *uint256.Int
S *uint256.Int `json:"s" gencodec:"required"` S *uint256.Int
} }
// BlobTxSidecar contains the blobs of a blob transaction. // BlobTxSidecar contains the blobs of a blob transaction.

View file

@ -37,9 +37,9 @@ type DynamicFeeTx struct {
AccessList AccessList AccessList AccessList
// Signature values // Signature values
V *big.Int `json:"v" gencodec:"required"` V *big.Int
R *big.Int `json:"r" gencodec:"required"` R *big.Int
S *big.Int `json:"s" gencodec:"required"` S *big.Int
} }
// copy creates a deep copy of the transaction data and initializes all fields. // copy creates a deep copy of the transaction data and initializes all fields.

View file

@ -49,7 +49,7 @@ func AddressToDelegation(addr common.Address) []byte {
// SetCodeTx implements the EIP-7702 transaction type which temporarily installs // SetCodeTx implements the EIP-7702 transaction type which temporarily installs
// the code at the signer's address. // the code at the signer's address.
type SetCodeTx struct { type SetCodeTx struct {
ChainID uint64 ChainID *uint256.Int
Nonce uint64 Nonce uint64
GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas
GasFeeCap *uint256.Int // a.k.a. maxFeePerGas GasFeeCap *uint256.Int // a.k.a. maxFeePerGas
@ -61,16 +61,16 @@ type SetCodeTx struct {
AuthList []SetCodeAuthorization AuthList []SetCodeAuthorization
// Signature values // Signature values
V *uint256.Int `json:"v" gencodec:"required"` V *uint256.Int
R *uint256.Int `json:"r" gencodec:"required"` R *uint256.Int
S *uint256.Int `json:"s" gencodec:"required"` S *uint256.Int
} }
//go:generate go run github.com/fjl/gencodec -type SetCodeAuthorization -field-override authorizationMarshaling -out gen_authorization.go //go:generate go run github.com/fjl/gencodec -type SetCodeAuthorization -field-override authorizationMarshaling -out gen_authorization.go
// SetCodeAuthorization is an authorization from an account to deploy code at its address. // SetCodeAuthorization is an authorization from an account to deploy code at its address.
type SetCodeAuthorization struct { type SetCodeAuthorization struct {
ChainID uint64 `json:"chainId" gencodec:"required"` ChainID uint256.Int `json:"chainId" gencodec:"required"`
Address common.Address `json:"address" gencodec:"required"` Address common.Address `json:"address" gencodec:"required"`
Nonce uint64 `json:"nonce" gencodec:"required"` Nonce uint64 `json:"nonce" gencodec:"required"`
V uint8 `json:"yParity" gencodec:"required"` V uint8 `json:"yParity" gencodec:"required"`
@ -80,7 +80,7 @@ type SetCodeAuthorization struct {
// field type overrides for gencodec // field type overrides for gencodec
type authorizationMarshaling struct { type authorizationMarshaling struct {
ChainID hexutil.Uint64 ChainID hexutil.U256
Nonce hexutil.Uint64 Nonce hexutil.Uint64
V hexutil.Uint64 V hexutil.Uint64
R hexutil.U256 R hexutil.U256
@ -180,7 +180,7 @@ func (tx *SetCodeTx) copy() TxData {
// accessors for innerTx. // accessors for innerTx.
func (tx *SetCodeTx) txType() byte { return SetCodeTxType } func (tx *SetCodeTx) txType() byte { return SetCodeTxType }
func (tx *SetCodeTx) chainID() *big.Int { return big.NewInt(int64(tx.ChainID)) } func (tx *SetCodeTx) chainID() *big.Int { return tx.ChainID.ToBig() }
func (tx *SetCodeTx) accessList() AccessList { return tx.AccessList } func (tx *SetCodeTx) accessList() AccessList { return tx.AccessList }
func (tx *SetCodeTx) data() []byte { return tx.Data } func (tx *SetCodeTx) data() []byte { return tx.Data }
func (tx *SetCodeTx) gas() uint64 { return tx.Gas } func (tx *SetCodeTx) gas() uint64 { return tx.Gas }
@ -207,7 +207,7 @@ func (tx *SetCodeTx) rawSignatureValues() (v, r, s *big.Int) {
} }
func (tx *SetCodeTx) setSignatureValues(chainID, v, r, s *big.Int) { func (tx *SetCodeTx) setSignatureValues(chainID, v, r, s *big.Int) {
tx.ChainID = chainID.Uint64() tx.ChainID = uint256.MustFromBig(chainID)
tx.V.SetFromBig(v) tx.V.SetFromBig(v)
tx.R.SetFromBig(r) tx.R.SetFromBig(r)
tx.S.SetFromBig(s) tx.S.SetFromBig(s)

View file

@ -57,6 +57,7 @@ var (
ShanghaiTime: u64(0), ShanghaiTime: u64(0),
VerkleTime: u64(0), VerkleTime: u64(0),
TerminalTotalDifficulty: common.Big0, TerminalTotalDifficulty: common.Big0,
EnableVerkleAtGenesis: true,
// TODO uncomment when proof generation is merged // TODO uncomment when proof generation is merged
// ProofInBlocks: true, // ProofInBlocks: true,
} }
@ -77,6 +78,7 @@ var (
ShanghaiTime: u64(0), ShanghaiTime: u64(0),
VerkleTime: u64(0), VerkleTime: u64(0),
TerminalTotalDifficulty: common.Big0, TerminalTotalDifficulty: common.Big0,
EnableVerkleAtGenesis: true,
} }
) )

View file

@ -109,8 +109,8 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
return nil, err return nil, err
} }
case RJUMPV: case RJUMPV:
max_size := int(code[i+1]) maxSize := int(code[i+1])
length := max_size + 1 length := maxSize + 1
if len(code) <= i+length { if len(code) <= i+length {
return nil, fmt.Errorf("%w: jump table truncated, op %s, pos %d", errTruncatedImmediate, op, i) return nil, fmt.Errorf("%w: jump table truncated, op %s, pos %d", errTruncatedImmediate, op, i)
} }
@ -120,7 +120,7 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
return nil, err return nil, err
} }
} }
i += 2 * max_size i += 2 * maxSize
case CALLF: case CALLF:
arg, _ := parseUint16(code[i+1:]) arg, _ := parseUint16(code[i+1:])
if arg >= len(container.types) { if arg >= len(container.types) {

View file

@ -19,6 +19,7 @@
// - There are not package guarantees. We might iterate heavily on this package, and do backwards-incompatible changes without warning // - There are not package guarantees. We might iterate heavily on this package, and do backwards-incompatible changes without warning
// - There are no quality-guarantees. These utilities may produce evm-code that is non-functional. YMMV. // - There are no quality-guarantees. These utilities may produce evm-code that is non-functional. YMMV.
// - There are no stability-guarantees. The utility will `panic` if the inputs do not align / make sense. // - There are no stability-guarantees. The utility will `panic` if the inputs do not align / make sense.
package program package program
import ( import (
@ -204,7 +205,7 @@ func (p *Program) StaticCall(gas *uint256.Int, address, inOffset, inSize, outOff
return p.Op(vm.STATICCALL) return p.Op(vm.STATICCALL)
} }
// StaticCall is a convenience function to make a callcode. If 'gas' is nil, the opcode GAS will // CallCode is a convenience function to make a callcode. If 'gas' is nil, the opcode GAS will
// be used to provide all gas. // be used to provide all gas.
func (p *Program) CallCode(gas *uint256.Int, address, value, inOffset, inSize, outOffset, outSize any) *Program { func (p *Program) CallCode(gas *uint256.Int, address, value, inOffset, inSize, outOffset, outSize any) *Program {
if outOffset == outSize && inSize == outSize && inOffset == outSize { if outOffset == outSize && inSize == outSize && inOffset == outSize {
@ -263,7 +264,7 @@ func (p *Program) InputAddressToStack(inputOffset uint32) *Program {
return p.Op(vm.AND) return p.Op(vm.AND)
} }
// MStore stores the provided data (into the memory area starting at memStart). // Mstore stores the provided data (into the memory area starting at memStart).
func (p *Program) Mstore(data []byte, memStart uint32) *Program { func (p *Program) Mstore(data []byte, memStart uint32) *Program {
var idx = 0 var idx = 0
// We need to store it in chunks of 32 bytes // We need to store it in chunks of 32 bytes

View file

@ -23,13 +23,13 @@ import (
) )
const ( const (
// The blocksize of BLAKE2b in bytes. // BlockSize the blocksize of BLAKE2b in bytes.
BlockSize = 128 BlockSize = 128
// The hash size of BLAKE2b-512 in bytes. // Size the hash size of BLAKE2b-512 in bytes.
Size = 64 Size = 64
// The hash size of BLAKE2b-384 in bytes. // Size384 the hash size of BLAKE2b-384 in bytes.
Size384 = 48 Size384 = 48
// The hash size of BLAKE2b-256 in bytes. // Size256 the hash size of BLAKE2b-256 in bytes.
Size256 = 32 Size256 = 32
) )

View file

@ -4,7 +4,7 @@ import (
"github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254"
) )
// Computes the following relation: ∏ᵢ e(Pᵢ, Qᵢ) =? 1 // PairingCheck computes the following relation: ∏ᵢ e(Pᵢ, Qᵢ) =? 1
// //
// To explain why gnark returns a (bool, error): // To explain why gnark returns a (bool, error):
// //

View file

@ -60,12 +60,12 @@ type PublicKey struct {
Params *ECIESParams Params *ECIESParams
} }
// Export an ECIES public key as an ECDSA public key. // ExportECDSA exports an ECIES public key as an ECDSA public key.
func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey { func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey {
return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y} return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y}
} }
// Import an ECDSA public key as an ECIES public key. // ImportECDSAPublic imports an ECDSA public key as an ECIES public key.
func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey {
return &PublicKey{ return &PublicKey{
X: pub.X, X: pub.X,
@ -81,20 +81,20 @@ type PrivateKey struct {
D *big.Int D *big.Int
} }
// Export an ECIES private key as an ECDSA private key. // ExportECDSA exports an ECIES private key as an ECDSA private key.
func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey { func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey {
pub := &prv.PublicKey pub := &prv.PublicKey
pubECDSA := pub.ExportECDSA() pubECDSA := pub.ExportECDSA()
return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D} return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D}
} }
// Import an ECDSA private key as an ECIES private key. // ImportECDSA imports an ECDSA private key as an ECIES private key.
func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
pub := ImportECDSAPublic(&prv.PublicKey) pub := ImportECDSAPublic(&prv.PublicKey)
return &PrivateKey{*pub, prv.D} return &PrivateKey{*pub, prv.D}
} }
// Generate an elliptic curve public / private keypair. If params is nil, // GenerateKey generates an elliptic curve public / private keypair. If params is nil,
// the recommended default parameters for the key will be chosen. // the recommended default parameters for the key will be chosen.
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
sk, err := ecdsa.GenerateKey(curve, rand) sk, err := ecdsa.GenerateKey(curve, rand)
@ -119,7 +119,7 @@ func MaxSharedKeyLength(pub *PublicKey) int {
return (pub.Curve.Params().BitSize + 7) / 8 return (pub.Curve.Params().BitSize + 7) / 8
} }
// ECDH key agreement method used to establish secret keys for encryption. // GenerateShared ECDH key agreement method used to establish secret keys for encryption.
func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) { func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
if prv.PublicKey.Curve != pub.Curve { if prv.PublicKey.Curve != pub.Curve {
return nil, ErrInvalidCurve return nil, ErrInvalidCurve

View file

@ -120,16 +120,23 @@ func NewOracle(backend OracleBackend, params Config, startPrice *big.Int) *Oracl
cache := lru.NewCache[cacheKey, processedFees](2048) cache := lru.NewCache[cacheKey, processedFees](2048)
headEvent := make(chan core.ChainHeadEvent, 1) headEvent := make(chan core.ChainHeadEvent, 1)
backend.SubscribeChainHeadEvent(headEvent) sub := backend.SubscribeChainHeadEvent(headEvent)
if sub != nil { // the gasprice testBackend doesn't support subscribing to head events
go func() { go func() {
var lastHead common.Hash var lastHead common.Hash
for ev := range headEvent { for {
select {
case ev := <-headEvent:
if ev.Header.ParentHash != lastHead { if ev.Header.ParentHash != lastHead {
cache.Purge() cache.Purge()
} }
lastHead = ev.Header.Hash() lastHead = ev.Header.Hash()
case <-sub.Err():
return
}
} }
}() }()
}
return &Oracle{ return &Oracle{
backend: backend, backend: backend,

View file

@ -174,6 +174,8 @@ func (p *Peer) dispatchResponse(res *Response, metadata func() interface{}) erro
return <-res.Done // Response delivered, return any errors return <-res.Done // Response delivered, return any errors
case <-res.Req.cancel: case <-res.Req.cancel:
return nil // Request cancelled, silently discard response return nil // Request cancelled, silently discard response
case <-p.term:
return errDisconnected
} }
} }

View file

@ -88,7 +88,7 @@ func testSnapSyncDisabling(t *testing.T, ethVer uint, snapVer uint) {
if err := empty.handler.downloader.BeaconSync(ethconfig.SnapSync, full.chain.CurrentBlock(), nil); err != nil { if err := empty.handler.downloader.BeaconSync(ethconfig.SnapSync, full.chain.CurrentBlock(), nil); err != nil {
t.Fatal("sync failed:", err) t.Fatal("sync failed:", err)
} }
empty.handler.enableSyncedFeatures() time.Sleep(time.Second * 5) // Downloader internally has to wait a timer (3s) to be expired before exiting
if empty.handler.snapSync.Load() { if empty.handler.snapSync.Load() {
t.Fatalf("snap sync not disabled after successful synchronisation") t.Fatalf("snap sync not disabled after successful synchronisation")

View file

@ -34,7 +34,7 @@ type Context struct {
TxHash common.Hash // Hash of the transaction being traced (zero if dangling call) TxHash common.Hash // Hash of the transaction being traced (zero if dangling call)
} }
// The set of methods that must be exposed by a tracer // Tracer represents the set of methods that must be exposed by a tracer
// for it to be available through the RPC interface. // for it to be available through the RPC interface.
// This involves a method to retrieve results and one to // This involves a method to retrieve results and one to
// stop tracing. // stop tracing.

View file

@ -13,6 +13,7 @@
// //
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package internal package internal
import ( import (

View file

@ -19,6 +19,7 @@ package logger
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"maps" "maps"
@ -350,7 +351,7 @@ func (l *StructLogger) GetResult() (json.RawMessage, error) {
returnData := common.CopyBytes(l.output) returnData := common.CopyBytes(l.output)
// Return data when successful and revert reason when reverted, otherwise empty. // Return data when successful and revert reason when reverted, otherwise empty.
returnVal := fmt.Sprintf("%x", returnData) returnVal := fmt.Sprintf("%x", returnData)
if failed && l.err != vm.ErrExecutionReverted { if failed && !errors.Is(l.err, vm.ErrExecutionReverted) {
returnVal = "" returnVal = ""
} }
return json.Marshal(&ExecutionResult{ return json.Marshal(&ExecutionResult{

View file

@ -12,7 +12,8 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. // along with go-ethereum. If not, see <http//www.gnu.org/licenses/>.
package era package era
import ( import (

View file

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
) )
@ -36,7 +37,7 @@ func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil
func TestStateOverrideMovePrecompile(t *testing.T) { func TestStateOverrideMovePrecompile(t *testing.T) {
db := state.NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil) db := state.NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil)
statedb, err := state.New(common.Hash{}, db) statedb, err := state.New(types.EmptyRootHash, db)
if err != nil { if err != nil {
t.Fatalf("failed to create statedb: %v", err) t.Fatalf("failed to create statedb: %v", err)
} }

View file

@ -45,7 +45,7 @@ const (
maxSimulateBlocks = 256 maxSimulateBlocks = 256
// timestampIncrement is the default increment between block timestamps. // timestampIncrement is the default increment between block timestamps.
timestampIncrement = 1 timestampIncrement = 12
) )
// simBlock is a batch of calls to be simulated sequentially. // simBlock is a batch of calls to be simulated sequentially.

View file

@ -41,19 +41,19 @@ func TestSimulateSanitizeBlockOrder(t *testing.T) {
baseNumber: 10, baseNumber: 10,
baseTimestamp: 50, baseTimestamp: 50,
blocks: []simBlock{{}, {}, {}}, blocks: []simBlock{{}, {}, {}},
expected: []result{{number: 11, timestamp: 51}, {number: 12, timestamp: 52}, {number: 13, timestamp: 53}}, expected: []result{{number: 11, timestamp: 62}, {number: 12, timestamp: 74}, {number: 13, timestamp: 86}},
}, },
{ {
baseNumber: 10, baseNumber: 10,
baseTimestamp: 50, baseTimestamp: 50,
blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(13), Time: newUint64(70)}}, {}}, blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(13), Time: newUint64(80)}}, {}},
expected: []result{{number: 11, timestamp: 51}, {number: 12, timestamp: 52}, {number: 13, timestamp: 70}, {number: 14, timestamp: 71}}, expected: []result{{number: 11, timestamp: 62}, {number: 12, timestamp: 74}, {number: 13, timestamp: 80}, {number: 14, timestamp: 92}},
}, },
{ {
baseNumber: 10, baseNumber: 10,
baseTimestamp: 50, baseTimestamp: 50,
blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(11)}}, {BlockOverrides: &override.BlockOverrides{Number: newInt(14)}}, {}}, blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(11)}}, {BlockOverrides: &override.BlockOverrides{Number: newInt(14)}}, {}},
expected: []result{{number: 11, timestamp: 51}, {number: 12, timestamp: 52}, {number: 13, timestamp: 53}, {number: 14, timestamp: 54}, {number: 15, timestamp: 55}}, expected: []result{{number: 11, timestamp: 62}, {number: 12, timestamp: 74}, {number: 13, timestamp: 86}, {number: 14, timestamp: 98}, {number: 15, timestamp: 110}},
}, },
{ {
baseNumber: 10, baseNumber: 10,
@ -64,8 +64,8 @@ func TestSimulateSanitizeBlockOrder(t *testing.T) {
{ {
baseNumber: 10, baseNumber: 10,
baseTimestamp: 50, baseTimestamp: 50,
blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(13), Time: newUint64(52)}}}, blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(13), Time: newUint64(74)}}},
err: "block timestamps must be in order: 52 <= 52", err: "block timestamps must be in order: 74 <= 74",
}, },
{ {
baseNumber: 10, baseNumber: 10,
@ -76,8 +76,8 @@ func TestSimulateSanitizeBlockOrder(t *testing.T) {
{ {
baseNumber: 10, baseNumber: 10,
baseTimestamp: 50, baseTimestamp: 50,
blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(11), Time: newUint64(60)}}, {BlockOverrides: &override.BlockOverrides{Number: newInt(13), Time: newUint64(61)}}}, blocks: []simBlock{{BlockOverrides: &override.BlockOverrides{Number: newInt(11), Time: newUint64(60)}}, {BlockOverrides: &override.BlockOverrides{Number: newInt(13), Time: newUint64(72)}}},
err: "block timestamps must be in order: 61 <= 61", err: "block timestamps must be in order: 72 <= 72",
}, },
} { } {
sim := &simulator{base: &types.Header{Number: big.NewInt(int64(tc.baseNumber)), Time: tc.baseTimestamp}} sim := &simulator{base: &types.Header{Number: big.NewInt(int64(tc.baseNumber)), Time: tc.baseTimestamp}}

View file

@ -503,7 +503,7 @@ func (args *TransactionArgs) ToTransaction(defaultType int) *types.Transaction {
} }
data = &types.SetCodeTx{ data = &types.SetCodeTx{
To: *args.To, To: *args.To,
ChainID: args.ChainID.ToInt().Uint64(), ChainID: uint256.MustFromBig(args.ChainID.ToInt()),
Nonce: uint64(*args.Nonce), Nonce: uint64(*args.Nonce),
Gas: uint64(*args.Gas), Gas: uint64(*args.Gas),
GasFeeCap: uint256.MustFromBig((*big.Int)(args.MaxFeePerGas)), GasFeeCap: uint256.MustFromBig((*big.Int)(args.MaxFeePerGas)),

View file

@ -67,7 +67,19 @@ type evalReq struct {
done chan bool done chan bool
} }
// runtime must be stopped with Stop() after use and cannot be used after stopping // New creates and initializes a new JavaScript runtime environment (JSRE).
// The runtime is configured with the provided assetPath for loading scripts and
// an output writer for logging or printing results.
//
// The returned JSRE must be stopped by calling Stop() after use to release resources.
// Attempting to use the JSRE after stopping it will result in undefined behavior.
//
// Parameters:
// - assetPath: The path to the directory containing script assets.
// - output: The writer used for logging or printing runtime output.
//
// Returns:
// - A pointer to the newly created JSRE instance.
func New(assetPath string, output io.Writer) *JSRE { func New(assetPath string, output io.Writer) *JSRE {
re := &JSRE{ re := &JSRE{
assetPath: assetPath, assetPath: assetPath,
@ -251,8 +263,15 @@ func (re *JSRE) Stop(waitForCallbacks bool) {
} }
} }
// Exec(file) loads and runs the contents of a file // Exec loads and executes the contents of a JavaScript file.
// if a relative path is given, the jsre's assetPath is used // If a relative path is provided, the file is resolved relative to the JSRE's assetPath.
// The file is read, compiled, and executed in the JSRE's runtime environment.
//
// Parameters:
// - file: The path to the JavaScript file to execute. Can be an absolute path or relative to assetPath.
//
// Returns:
// - error: An error if the file cannot be read, compiled, or executed.
func (re *JSRE) Exec(file string) error { func (re *JSRE) Exec(file string) error {
code, err := os.ReadFile(common.AbsolutePath(re.assetPath, file)) code, err := os.ReadFile(common.AbsolutePath(re.assetPath, file))
if err != nil { if err != nil {

View file

@ -7,6 +7,7 @@
// we require because of the forking limitations of using Go. Handlers can be // we require because of the forking limitations of using Go. Handlers can be
// registered with a name and the argv 0 of the exec of the binary will be used // registered with a name and the argv 0 of the exec of the binary will be used
// to find and execute custom init paths. // to find and execute custom init paths.
package reexec package reexec
import ( import (

View file

@ -1,5 +1,6 @@
// Hook go-metrics into expvar // Hook go-metrics into expvar
// on any /debug/metrics request, load all vars from the registry into expvar, and execute regular expvar handler // on any /debug/metrics request, load all vars from the registry into expvar, and execute regular expvar handler
package exp package exp
import ( import (

View file

@ -39,7 +39,7 @@ func NewRegisteredGaugeInfo(name string, r Registry) *GaugeInfo {
return c return c
} }
// gaugeInfoSnapshot is a read-only copy of another GaugeInfo. // GaugeInfoSnapshot is a read-only copy of another GaugeInfo.
type GaugeInfoSnapshot GaugeInfoValue type GaugeInfoSnapshot GaugeInfoValue
// Value returns the value at the time the snapshot was taken. // Value returns the value at the time the snapshot was taken.

View file

@ -12,7 +12,7 @@ func Log(r Registry, freq time.Duration, l Logger) {
LogScaled(r, freq, time.Nanosecond, l) LogScaled(r, freq, time.Nanosecond, l)
} }
// Output each metric in the given registry periodically using the given // LogScaled outputs each metric in the given registry periodically using the given
// logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos. // logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos.
func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) { func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
du := float64(scale) du := float64(scale)

View file

@ -3,6 +3,7 @@
// <https://github.com/rcrowley/go-metrics> // <https://github.com/rcrowley/go-metrics>
// //
// Coda Hale's original work: <https://github.com/codahale/metrics> // Coda Hale's original work: <https://github.com/codahale/metrics>
package metrics package metrics
import ( import (

View file

@ -53,14 +53,14 @@ func (t *ResettingTimer) Snapshot() *ResettingTimerSnapshot {
return snapshot return snapshot
} }
// Record the duration of the execution of the given function. // Time records the duration of the execution of the given function.
func (t *ResettingTimer) Time(f func()) { func (t *ResettingTimer) Time(f func()) {
ts := time.Now() ts := time.Now()
f() f()
t.Update(time.Since(ts)) t.Update(time.Since(ts))
} }
// Record the duration of an event. // Update records the duration of an event.
func (t *ResettingTimer) Update(d time.Duration) { func (t *ResettingTimer) Update(d time.Duration) {
if !metricsEnabled { if !metricsEnabled {
return return
@ -71,7 +71,7 @@ func (t *ResettingTimer) Update(d time.Duration) {
t.sum += int64(d) t.sum += int64(d)
} }
// Record the duration of an event that started at a time and ends now. // UpdateSince records the duration of an event that started at a time and ends now.
func (t *ResettingTimer) UpdateSince(ts time.Time) { func (t *ResettingTimer) UpdateSince(ts time.Time) {
t.Update(time.Since(ts)) t.Update(time.Since(ts))
} }

View file

@ -9,7 +9,7 @@ import (
"time" "time"
) )
// Output each metric in the given registry to syslog periodically using // Syslog outputs each metric in the given registry to syslog periodically using
// the given syslogger. // the given syslogger.
func Syslog(r Registry, d time.Duration, w *syslog.Writer) { func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
for range time.Tick(d) { for range time.Tick(d) {

View file

@ -145,7 +145,7 @@ func createMiner(t *testing.T) *Miner {
chainDB := rawdb.NewMemoryDatabase() chainDB := rawdb.NewMemoryDatabase()
triedb := triedb.NewDatabase(chainDB, nil) triedb := triedb.NewDatabase(chainDB, nil)
genesis := minerTestGenesisBlock(15, 11_500_000, common.HexToAddress("12345")) genesis := minerTestGenesisBlock(15, 11_500_000, common.HexToAddress("12345"))
chainConfig, _, err := core.SetupGenesisBlock(chainDB, triedb, genesis) chainConfig, _, _, err := core.SetupGenesisBlock(chainDB, triedb, genesis)
if err != nil { if err != nil {
t.Fatalf("can't create new chain config: %v", err) t.Fatalf("can't create new chain config: %v", err)
} }

View file

@ -249,20 +249,20 @@ func TestHandshake_BadHandshakeAttack(t *testing.T) {
net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou) net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou)
// A -> B FINDNODE // A -> B FINDNODE
incorrect_challenge := &Whoareyou{ incorrectChallenge := &Whoareyou{
IDNonce: [16]byte{5, 6, 7, 8, 9, 6, 11, 12}, IDNonce: [16]byte{5, 6, 7, 8, 9, 6, 11, 12},
RecordSeq: challenge.RecordSeq, RecordSeq: challenge.RecordSeq,
Node: challenge.Node, Node: challenge.Node,
sent: challenge.sent, sent: challenge.sent,
} }
incorrect_findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, incorrect_challenge, &Findnode{}) incorrectFindNode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, incorrectChallenge, &Findnode{})
incorrect_findnode2 := make([]byte, len(incorrect_findnode)) incorrectFindNode2 := make([]byte, len(incorrectFindNode))
copy(incorrect_findnode2, incorrect_findnode) copy(incorrectFindNode2, incorrectFindNode)
net.nodeB.expectDecodeErr(t, errInvalidNonceSig, incorrect_findnode) net.nodeB.expectDecodeErr(t, errInvalidNonceSig, incorrectFindNode)
// Reject new findnode as previous handshake is now deleted. // Reject new findnode as previous handshake is now deleted.
net.nodeB.expectDecodeErr(t, errUnexpectedHandshake, incorrect_findnode2) net.nodeB.expectDecodeErr(t, errUnexpectedHandshake, incorrectFindNode2)
// The findnode packet is again rejected even with a valid challenge this time. // The findnode packet is again rejected even with a valid challenge this time.
findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{}) findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{})

View file

@ -326,6 +326,19 @@ type ChainConfig struct {
DepositContractAddress common.Address `json:"depositContractAddress,omitempty"` DepositContractAddress common.Address `json:"depositContractAddress,omitempty"`
// EnableVerkleAtGenesis is a flag that specifies whether the network uses
// the Verkle tree starting from the genesis block. If set to true, the
// genesis state will be committed using the Verkle tree, eliminating the
// need for any Verkle transition later.
//
// This is a temporary flag only for verkle devnet testing, where verkle is
// activated at genesis, and the configured activation date has already passed.
//
// In production networks (mainnet and public testnets), verkle activation
// always occurs after the genesis block, making this flag irrelevant in
// those cases.
EnableVerkleAtGenesis bool `json:"enableVerkleAtGenesis,omitempty"`
// Various consensus engines // Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"` Ethash *EthashConfig `json:"ethash,omitempty"`
Clique *CliqueConfig `json:"clique,omitempty"` Clique *CliqueConfig `json:"clique,omitempty"`
@ -525,6 +538,20 @@ func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time) return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time)
} }
// IsVerkleGenesis checks whether the verkle fork is activated at the genesis block.
//
// Verkle mode is considered enabled if the verkle fork time is configured,
// regardless of whether the local time has surpassed the fork activation time.
// This is a temporary workaround for verkle devnet testing, where verkle is
// activated at genesis, and the configured activation date has already passed.
//
// In production networks (mainnet and public testnets), verkle activation
// always occurs after the genesis block, making this function irrelevant in
// those cases.
func (c *ChainConfig) IsVerkleGenesis() bool {
return c.EnableVerkleAtGenesis
}
// IsEIP4762 returns whether eip 4762 has been activated at given block. // IsEIP4762 returns whether eip 4762 has been activated at given block.
func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool { func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool {
return c.IsVerkle(num, time) return c.IsVerkle(num, time)

View file

@ -179,7 +179,7 @@ const (
HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935. HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935.
) )
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations // Bls12381MultiExpDiscountTable gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
var Bls12381MultiExpDiscountTable = [128]uint64{1200, 888, 764, 641, 594, 547, 500, 453, 438, 423, 408, 394, 379, 364, 349, 334, 330, 326, 322, 318, 314, 310, 306, 302, 298, 294, 289, 285, 281, 277, 273, 269, 268, 266, 265, 263, 262, 260, 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 241, 239, 238, 236, 235, 233, 232, 231, 229, 228, 226, 225, 223, 222, 221, 220, 219, 219, 218, 217, 216, 216, 215, 214, 213, 213, 212, 211, 211, 210, 209, 208, 208, 207, 206, 205, 205, 204, 203, 202, 202, 201, 200, 199, 199, 198, 197, 196, 196, 195, 194, 193, 193, 192, 191, 191, 190, 189, 188, 188, 187, 186, 185, 185, 184, 183, 182, 182, 181, 180, 179, 179, 178, 177, 176, 176, 175, 174} var Bls12381MultiExpDiscountTable = [128]uint64{1200, 888, 764, 641, 594, 547, 500, 453, 438, 423, 408, 394, 379, 364, 349, 334, 330, 326, 322, 318, 314, 310, 306, 302, 298, 294, 289, 285, 281, 277, 273, 269, 268, 266, 265, 263, 262, 260, 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 241, 239, 238, 236, 235, 233, 232, 231, 229, 228, 226, 225, 223, 222, 221, 220, 219, 219, 218, 217, 216, 216, 215, 214, 213, 213, 212, 211, 211, 210, 209, 208, 208, 207, 206, 205, 205, 204, 203, 202, 202, 201, 200, 199, 199, 198, 197, 196, 196, 195, 194, 193, 193, 192, 191, 191, 190, 189, 188, 188, 187, 186, 185, 185, 184, 183, 182, 182, 181, 180, 179, 179, 178, 177, 176, 176, 175, 174}
// Difficulty parameters. // Difficulty parameters.

View file

@ -664,7 +664,7 @@ func (api *SignerAPI) SignGnosisSafeTx(ctx context.Context, signerAddress common
return &gnosisTx, nil return &gnosisTx, nil
} }
// Returns the external api version. This method does not require user acceptance. Available methods are // Version returns the external api version. This method does not require user acceptance. Available methods are
// available via enumeration anyway, and this info does not contain user-specific data // available via enumeration anyway, and this info does not contain user-specific data
func (api *SignerAPI) Version(ctx context.Context) (string, error) { func (api *SignerAPI) Version(ctx context.Context) (string, error) {
return ExternalAPIVersion, nil return ExternalAPIVersion, nil

View file

@ -48,7 +48,7 @@ func NewUIServerAPI(extapi *SignerAPI) *UIServerAPI {
return &UIServerAPI{extapi, extapi.am} return &UIServerAPI{extapi, extapi.am}
} }
// List available accounts. As opposed to the external API definition, this method delivers // ListAccounts lists available accounts. As opposed to the external API definition, this method delivers
// the full Account object and not only Address. // the full Account object and not only Address.
// Example call // Example call
// {"jsonrpc":"2.0","method":"clef_listAccounts","params":[], "id":4} // {"jsonrpc":"2.0","method":"clef_listAccounts","params":[], "id":4}

View file

@ -16,7 +16,7 @@ var _ = (*stAuthorizationMarshaling)(nil)
// MarshalJSON marshals as JSON. // MarshalJSON marshals as JSON.
func (s stAuthorization) MarshalJSON() ([]byte, error) { func (s stAuthorization) MarshalJSON() ([]byte, error) {
type stAuthorization struct { type stAuthorization struct {
ChainID math.HexOrDecimal64 ChainID *math.HexOrDecimal256 `json:"chainId" gencodec:"required"`
Address common.Address `json:"address" gencodec:"required"` Address common.Address `json:"address" gencodec:"required"`
Nonce math.HexOrDecimal64 `json:"nonce" gencodec:"required"` Nonce math.HexOrDecimal64 `json:"nonce" gencodec:"required"`
V math.HexOrDecimal64 `json:"v" gencodec:"required"` V math.HexOrDecimal64 `json:"v" gencodec:"required"`
@ -24,7 +24,7 @@ func (s stAuthorization) MarshalJSON() ([]byte, error) {
S *math.HexOrDecimal256 `json:"s" gencodec:"required"` S *math.HexOrDecimal256 `json:"s" gencodec:"required"`
} }
var enc stAuthorization var enc stAuthorization
enc.ChainID = math.HexOrDecimal64(s.ChainID) enc.ChainID = (*math.HexOrDecimal256)(s.ChainID)
enc.Address = s.Address enc.Address = s.Address
enc.Nonce = math.HexOrDecimal64(s.Nonce) enc.Nonce = math.HexOrDecimal64(s.Nonce)
enc.V = math.HexOrDecimal64(s.V) enc.V = math.HexOrDecimal64(s.V)
@ -36,7 +36,7 @@ func (s stAuthorization) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON. // UnmarshalJSON unmarshals from JSON.
func (s *stAuthorization) UnmarshalJSON(input []byte) error { func (s *stAuthorization) UnmarshalJSON(input []byte) error {
type stAuthorization struct { type stAuthorization struct {
ChainID *math.HexOrDecimal64 ChainID *math.HexOrDecimal256 `json:"chainId" gencodec:"required"`
Address *common.Address `json:"address" gencodec:"required"` Address *common.Address `json:"address" gencodec:"required"`
Nonce *math.HexOrDecimal64 `json:"nonce" gencodec:"required"` Nonce *math.HexOrDecimal64 `json:"nonce" gencodec:"required"`
V *math.HexOrDecimal64 `json:"v" gencodec:"required"` V *math.HexOrDecimal64 `json:"v" gencodec:"required"`
@ -47,9 +47,10 @@ func (s *stAuthorization) UnmarshalJSON(input []byte) error {
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
return err return err
} }
if dec.ChainID != nil { if dec.ChainID == nil {
s.ChainID = uint64(*dec.ChainID) return errors.New("missing required field 'chainId' for stAuthorization")
} }
s.ChainID = (*big.Int)(dec.ChainID)
if dec.Address == nil { if dec.Address == nil {
return errors.New("missing required field 'address' for stAuthorization") return errors.New("missing required field 'address' for stAuthorization")
} }

View file

@ -140,7 +140,7 @@ type stTransactionMarshaling struct {
// Authorization is an authorization from an account to deploy code at it's address. // Authorization is an authorization from an account to deploy code at it's address.
type stAuthorization struct { type stAuthorization struct {
ChainID uint64 ChainID *big.Int `json:"chainId" gencodec:"required"`
Address common.Address `json:"address" gencodec:"required"` Address common.Address `json:"address" gencodec:"required"`
Nonce uint64 `json:"nonce" gencodec:"required"` Nonce uint64 `json:"nonce" gencodec:"required"`
V uint8 `json:"v" gencodec:"required"` V uint8 `json:"v" gencodec:"required"`
@ -150,7 +150,7 @@ type stAuthorization struct {
// field type overrides for gencodec // field type overrides for gencodec
type stAuthorizationMarshaling struct { type stAuthorizationMarshaling struct {
ChainID math.HexOrDecimal64 ChainID *math.HexOrDecimal256
Nonce math.HexOrDecimal64 Nonce math.HexOrDecimal64
V math.HexOrDecimal64 V math.HexOrDecimal64
R *math.HexOrDecimal256 R *math.HexOrDecimal256
@ -446,7 +446,7 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Mess
authList = make([]types.SetCodeAuthorization, len(tx.AuthorizationList)) authList = make([]types.SetCodeAuthorization, len(tx.AuthorizationList))
for i, auth := range tx.AuthorizationList { for i, auth := range tx.AuthorizationList {
authList[i] = types.SetCodeAuthorization{ authList[i] = types.SetCodeAuthorization{
ChainID: auth.ChainID, ChainID: *uint256.MustFromBig(auth.ChainID),
Address: auth.Address, Address: auth.Address,
Nonce: auth.Nonce, Nonce: auth.Nonce,
V: auth.V, V: auth.V,

View file

@ -19,7 +19,6 @@ package trie
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/triedb/database" "github.com/ethereum/go-ethereum/triedb/database"
) )
@ -34,9 +33,6 @@ type trieReader struct {
// newTrieReader initializes the trie reader with the given node reader. // newTrieReader initializes the trie reader with the given node reader.
func newTrieReader(stateRoot, owner common.Hash, db database.NodeDatabase) (*trieReader, error) { func newTrieReader(stateRoot, owner common.Hash, db database.NodeDatabase) (*trieReader, error) {
if stateRoot == (common.Hash{}) || stateRoot == types.EmptyRootHash { if stateRoot == (common.Hash{}) || stateRoot == types.EmptyRootHash {
if stateRoot == (common.Hash{}) {
log.Error("Zero state root hash!")
}
return &trieReader{owner: owner}, nil return &trieReader{owner: owner}, nil
} }
reader, err := db.NodeReader(stateRoot) reader, err := db.NodeReader(stateRoot)

View file

@ -64,10 +64,6 @@ type backend interface {
// state. An error will be returned if the specified state is not available. // state. An error will be returned if the specified state is not available.
StateReader(root common.Hash) (database.StateReader, error) StateReader(root common.Hash) (database.StateReader, error)
// Initialized returns an indicator if the state data is already initialized
// according to the state scheme.
Initialized(genesisRoot common.Hash) bool
// Size returns the current storage size of the diff layers on top of the // Size returns the current storage size of the diff layers on top of the
// disk layer and the storage size of the nodes cached in the disk layer. // disk layer and the storage size of the nodes cached in the disk layer.
// //
@ -178,12 +174,6 @@ func (db *Database) Size() (common.StorageSize, common.StorageSize, common.Stora
return diffs, nodes, preimages return diffs, nodes, preimages
} }
// Initialized returns an indicator if the state data is already initialized
// according to the state scheme.
func (db *Database) Initialized(genesisRoot common.Hash) bool {
return db.backend.Initialized(genesisRoot)
}
// Scheme returns the node scheme used in the database. // Scheme returns the node scheme used in the database.
func (db *Database) Scheme() string { func (db *Database) Scheme() string {
if db.config.PathDB != nil { if db.config.PathDB != nil {

View file

@ -532,12 +532,6 @@ func (c *cleaner) Delete(key []byte) error {
panic("not implemented") panic("not implemented")
} }
// Initialized returns an indicator if state data is already initialized
// in hash-based scheme by checking the presence of genesis state.
func (db *Database) Initialized(genesisRoot common.Hash) bool {
return rawdb.HasLegacyTrieNode(db.diskdb, genesisRoot)
}
// Update inserts the dirty nodes in provided nodeset into database and link the // Update inserts the dirty nodes in provided nodeset into database and link the
// account trie with multiple storage tries if necessary. // account trie with multiple storage tries if necessary.
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet) error { func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet) error {

View file

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-verkle"
) )
const ( const (
@ -148,6 +149,29 @@ var Defaults = &Config{
// ReadOnly is the config in order to open database in read only mode. // ReadOnly is the config in order to open database in read only mode.
var ReadOnly = &Config{ReadOnly: true} var ReadOnly = &Config{ReadOnly: true}
// nodeHasher is the function to compute the hash of supplied node blob.
type nodeHasher func([]byte) (common.Hash, error)
// merkleNodeHasher computes the hash of the given merkle node.
func merkleNodeHasher(blob []byte) (common.Hash, error) {
if len(blob) == 0 {
return types.EmptyRootHash, nil
}
return crypto.Keccak256Hash(blob), nil
}
// verkleNodeHasher computes the hash of the given verkle node.
func verkleNodeHasher(blob []byte) (common.Hash, error) {
if len(blob) == 0 {
return types.EmptyVerkleHash, nil
}
n, err := verkle.ParseNode(blob, 0)
if err != nil {
return common.Hash{}, err
}
return n.Commit().Bytes(), nil
}
// Database is a multiple-layered structure for maintaining in-memory states // Database is a multiple-layered structure for maintaining in-memory states
// along with its dirty trie nodes. It consists of one persistent base layer // along with its dirty trie nodes. It consists of one persistent base layer
// backed by a key-value store, on top of which arbitrarily many in-memory diff // backed by a key-value store, on top of which arbitrarily many in-memory diff
@ -167,6 +191,7 @@ type Database struct {
readOnly bool // Flag if database is opened in read only mode readOnly bool // Flag if database is opened in read only mode
waitSync bool // Flag if database is deactivated due to initial state sync waitSync bool // Flag if database is deactivated due to initial state sync
isVerkle bool // Flag if database is used for verkle tree isVerkle bool // Flag if database is used for verkle tree
hasher nodeHasher // Trie node hasher
config *Config // Configuration for database config *Config // Configuration for database
diskdb ethdb.Database // Persistent storage for matured trie nodes diskdb ethdb.Database // Persistent storage for matured trie nodes
@ -184,19 +209,21 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
} }
config = config.sanitize() config = config.sanitize()
db := &Database{
readOnly: config.ReadOnly,
isVerkle: isVerkle,
config: config,
diskdb: diskdb,
hasher: merkleNodeHasher,
}
// Establish a dedicated database namespace tailored for verkle-specific // Establish a dedicated database namespace tailored for verkle-specific
// data, ensuring the isolation of both verkle and merkle tree data. It's // data, ensuring the isolation of both verkle and merkle tree data. It's
// important to note that the introduction of a prefix won't lead to // important to note that the introduction of a prefix won't lead to
// substantial storage overhead, as the underlying database will efficiently // substantial storage overhead, as the underlying database will efficiently
// compress the shared key prefix. // compress the shared key prefix.
if isVerkle { if isVerkle {
diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix)) db.diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix))
} db.hasher = verkleNodeHasher
db := &Database{
readOnly: config.ReadOnly,
isVerkle: isVerkle,
config: config,
diskdb: diskdb,
} }
// Construct the layer tree by resolving the in-disk singleton state // Construct the layer tree by resolving the in-disk singleton state
// and in-memory layer journal. // and in-memory layer journal.
@ -277,6 +304,8 @@ func (db *Database) repairHistory() error {
// //
// The passed in maps(nodes, states) will be retained to avoid copying everything. // The passed in maps(nodes, states) will be retained to avoid copying everything.
// Therefore, these maps must not be changed afterwards. // Therefore, these maps must not be changed afterwards.
//
// The supplied parentRoot and root must be a valid trie hash value.
func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *StateSetWithOrigin) error { func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *StateSetWithOrigin) error {
// Hold the lock to prevent concurrent mutations. // Hold the lock to prevent concurrent mutations.
db.lock.Lock() db.lock.Lock()
@ -350,10 +379,9 @@ func (db *Database) Enable(root common.Hash) error {
return errDatabaseReadOnly return errDatabaseReadOnly
} }
// Ensure the provided state root matches the stored one. // Ensure the provided state root matches the stored one.
root = types.TrieRootHash(root) stored, err := db.hasher(rawdb.ReadAccountTrieNode(db.diskdb, nil))
stored := types.EmptyRootHash if err != nil {
if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { return err
stored = crypto.Keccak256Hash(blob)
} }
if stored != root { if stored != root {
return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root) return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root)
@ -389,6 +417,8 @@ func (db *Database) Enable(root common.Hash) error {
// Recover rollbacks the database to a specified historical point. // Recover rollbacks the database to a specified historical point.
// The state is supported as the rollback destination only if it's // The state is supported as the rollback destination only if it's
// canonical state and the corresponding trie histories are existent. // canonical state and the corresponding trie histories are existent.
//
// The supplied root must be a valid trie hash value.
func (db *Database) Recover(root common.Hash) error { func (db *Database) Recover(root common.Hash) error {
db.lock.Lock() db.lock.Lock()
defer db.lock.Unlock() defer db.lock.Unlock()
@ -401,7 +431,6 @@ func (db *Database) Recover(root common.Hash) error {
return errors.New("state rollback is non-supported") return errors.New("state rollback is non-supported")
} }
// Short circuit if the target state is not recoverable // Short circuit if the target state is not recoverable
root = types.TrieRootHash(root)
if !db.Recoverable(root) { if !db.Recoverable(root) {
return errStateUnrecoverable return errStateUnrecoverable
} }
@ -434,9 +463,10 @@ func (db *Database) Recover(root common.Hash) error {
} }
// Recoverable returns the indicator if the specified state is recoverable. // Recoverable returns the indicator if the specified state is recoverable.
//
// The supplied root must be a valid trie hash value.
func (db *Database) Recoverable(root common.Hash) bool { func (db *Database) Recoverable(root common.Hash) bool {
// Ensure the requested state is a known state. // Ensure the requested state is a known state.
root = types.TrieRootHash(root)
id := rawdb.ReadStateID(db.diskdb, root) id := rawdb.ReadStateID(db.diskdb, root)
if id == nil { if id == nil {
return false return false
@ -499,21 +529,6 @@ func (db *Database) Size() (diffs common.StorageSize, nodes common.StorageSize)
return diffs, nodes return diffs, nodes
} }
// Initialized returns an indicator if the state data is already
// initialized in path-based scheme.
func (db *Database) Initialized(genesisRoot common.Hash) bool {
var inited bool
db.tree.forEach(func(layer layer) {
if layer.rootHash() != types.EmptyRootHash {
inited = true
}
})
if !inited {
inited = rawdb.ReadSnapSyncStatusFlag(db.diskdb) != rawdb.StateSyncUnknown
}
return inited
}
// modifyAllowed returns the indicator if mutation is allowed. This function // modifyAllowed returns the indicator if mutation is allowed. This function
// assumes the db.lock is already held. // assumes the db.lock is already held.
func (db *Database) modifyAllowed() error { func (db *Database) modifyAllowed() error {

View file

@ -222,7 +222,12 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode
dirties = make(map[common.Hash]struct{}) dirties = make(map[common.Hash]struct{})
) )
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
switch rand.Intn(opLen) { // Start with account creation always
op := createAccountOp
if i > 0 {
op = rand.Intn(opLen)
}
switch op {
case createAccountOp: case createAccountOp:
// account creation // account creation
addr := testrand.Address() addr := testrand.Address()
@ -453,8 +458,8 @@ func TestDatabaseRecoverable(t *testing.T) {
// Initial state should be recoverable // Initial state should be recoverable
{types.EmptyRootHash, true}, {types.EmptyRootHash, true},
// Initial state should be recoverable // common.Hash{} is not a valid state root for revert
{common.Hash{}, true}, {common.Hash{}, false},
// Layers below current disk layer are recoverable // Layers below current disk layer are recoverable
{tester.roots[index-1], true}, {tester.roots[index-1], true},

View file

@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -93,9 +92,9 @@ func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) {
// loadLayers loads a pre-existing state layer backed by a key-value store. // loadLayers loads a pre-existing state layer backed by a key-value store.
func (db *Database) loadLayers() layer { func (db *Database) loadLayers() layer {
// Retrieve the root node of persistent state. // Retrieve the root node of persistent state.
var root = types.EmptyRootHash root, err := db.hasher(rawdb.ReadAccountTrieNode(db.diskdb, nil))
if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { if err != nil {
root = crypto.Keccak256Hash(blob) log.Crit("Failed to compute node hash", "err", err)
} }
// Load the layers by resolving the journal // Load the layers by resolving the journal
head, err := db.loadJournal(root) head, err := db.loadJournal(root)
@ -236,6 +235,8 @@ func (dl *diffLayer) journal(w io.Writer) error {
// This is meant to be used during shutdown to persist the layer without // This is meant to be used during shutdown to persist the layer without
// flattening everything down (bad for reorgs). And this function will mark the // flattening everything down (bad for reorgs). And this function will mark the
// database as read-only to prevent all following mutation to disk. // database as read-only to prevent all following mutation to disk.
//
// The supplied root must be a valid trie hash value.
func (db *Database) Journal(root common.Hash) error { func (db *Database) Journal(root common.Hash) error {
// Retrieve the head layer to journal from. // Retrieve the head layer to journal from.
l := db.tree.get(root) l := db.tree.get(root)
@ -265,9 +266,9 @@ func (db *Database) Journal(root common.Hash) error {
} }
// Secondly write out the state root in disk, ensure all layers // Secondly write out the state root in disk, ensure all layers
// on top are continuous with disk. // on top are continuous with disk.
diskRoot := types.EmptyRootHash diskRoot, err := db.hasher(rawdb.ReadAccountTrieNode(db.diskdb, nil))
if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { if err != nil {
diskRoot = crypto.Keccak256Hash(blob) return err
} }
if err := rlp.Encode(journal, diskRoot); err != nil { if err := rlp.Encode(journal, diskRoot); err != nil {
return err return err

View file

@ -22,7 +22,6 @@ import (
"sync" "sync"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
) )
@ -62,7 +61,7 @@ func (tree *layerTree) get(root common.Hash) layer {
tree.lock.RLock() tree.lock.RLock()
defer tree.lock.RUnlock() defer tree.lock.RUnlock()
return tree.layers[types.TrieRootHash(root)] return tree.layers[root]
} }
// forEach iterates the stored layers inside and applies the // forEach iterates the stored layers inside and applies the
@ -92,7 +91,6 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6
// //
// Although we could silently ignore this internally, it should be the caller's // Although we could silently ignore this internally, it should be the caller's
// responsibility to avoid even attempting to insert such a layer. // responsibility to avoid even attempting to insert such a layer.
root, parentRoot = types.TrieRootHash(root), types.TrieRootHash(parentRoot)
if root == parentRoot { if root == parentRoot {
return errors.New("layer cycle") return errors.New("layer cycle")
} }
@ -112,7 +110,6 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6
// are crossed. All diffs beyond the permitted number are flattened downwards. // are crossed. All diffs beyond the permitted number are flattened downwards.
func (tree *layerTree) cap(root common.Hash, layers int) error { func (tree *layerTree) cap(root common.Hash, layers int) error {
// Retrieve the head layer to cap from // Retrieve the head layer to cap from
root = types.TrieRootHash(root)
l := tree.get(root) l := tree.get(root)
if l == nil { if l == nil {
return fmt.Errorf("triedb layer [%#x] missing", root) return fmt.Errorf("triedb layer [%#x] missing", root)