From eb4d322470bdccf2040e1c70f29f3f1c7a600565 Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Thu, 28 Apr 2022 10:56:40 +0200 Subject: [PATCH 01/83] Implement geth-embedded builder API --- README.md | 392 +++--------------------------- README.original.md | 379 +++++++++++++++++++++++++++++ builder/backend.go | 436 ++++++++++++++++++++++++++++++++++ builder/backend_test.go | 233 ++++++++++++++++++ builder/beacon_client.go | 200 ++++++++++++++++ builder/beacon_client_test.go | 268 +++++++++++++++++++++ builder/index.go | 90 +++++++ builder/service.go | 108 +++++++++ builder/validator.go | 49 ++++ cmd/geth/config.go | 14 +- cmd/geth/main.go | 11 + cmd/utils/flags.go | 50 +++- core/beacon/types.go | 1 + core/types/block.go | 2 + eth/backend.go | 25 ++ eth/catalyst/api.go | 16 +- eth/catalyst/api_test.go | 4 +- eth/catalyst/queue.go | 9 +- go.mod | 51 ++-- go.sum | 169 +++++++------ miner/miner.go | 8 +- miner/stress/beacon/main.go | 11 +- miner/worker.go | 21 +- miner/worker_test.go | 4 +- 24 files changed, 2060 insertions(+), 491 deletions(-) create mode 100644 README.original.md create mode 100644 builder/backend.go create mode 100644 builder/backend_test.go create mode 100644 builder/beacon_client.go create mode 100644 builder/beacon_client_test.go create mode 100644 builder/index.go create mode 100644 builder/service.go create mode 100644 builder/validator.go diff --git a/README.md b/README.md index b20eb5b748..f831771269 100644 --- a/README.md +++ b/README.md @@ -1,379 +1,43 @@ -## Go Ethereum +[geth readme](README.original.md) -Official Golang implementation of the Ethereum protocol. +# Builder API -[![API Reference]( -https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667 -)](https://pkg.go.dev/github.com/ethereum/go-ethereum?tab=doc) -[![Go Report Card](https://goreportcard.com/badge/github.com/ethereum/go-ethereum)](https://goreportcard.com/report/github.com/ethereum/go-ethereum) -[![Travis](https://travis-ci.com/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.com/ethereum/go-ethereum) -[![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.gg/nthXNEv) +Builder API implementing [builder spec](https://github.com/ethereum/builder-specs), making geth into a standalone block builder. -Automated builds are available for stable releases and the unstable master branch. Binary -archives are published at https://geth.ethereum.org/downloads/. +Run on your favorite network, including Kiln and local devnet. -## Building the source +Requires forkchoice update to be sent for block building, on public testnets run beacon node modified to send forkchoice update on every slot [example modified beacon client (lighthouse)](https://github.com/flashbots/lighthouse) -For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/install-and-build/installing-geth). +Test with [mev-boost](https://github.com/flashbots/mev-boost) and [mev-boost test cli](https://github.com/flashbots/mev-boost/tree/main/cmd/test-cli). -Building `geth` requires both a Go (version 1.16 or later) and a C compiler. You can install -them using your favourite package manager. Once the dependencies are installed, run +Provides summary page at the listening address' root (http://localhost:28545 by default). -```shell -make geth -``` - -or, to build the full suite of utilities: - -```shell -make all -``` - -## Executables - -The go-ethereum project comes with several wrappers/executables found in the `cmd` -directory. - -| Command | Description | -| :-----------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/interface/command-line-options) for command line options. | -| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. | -| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. | -| `abigen` | Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/dapp/native-bindings) page for details. | -| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. | -| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). | -| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). | -| `puppeth` | a CLI wizard that aids in creating a new Ethereum network. | - -## Running `geth` - -Going through all the possible command line flags is out of scope here (please consult our -[CLI Wiki page](https://geth.ethereum.org/docs/interface/command-line-options)), -but we've enumerated a few common parameter combos to get you up to speed quickly -on how you can run your own `geth` instance. - -### Hardware Requirements - -Minimum: - -* CPU with 2+ cores -* 4GB RAM -* 1TB free storage space to sync the Mainnet -* 8 MBit/sec download Internet service - -Recommended: - -* Fast CPU with 4+ cores -* 16GB+ RAM -* High Performance SSD with at least 1TB free space -* 25+ MBit/sec download Internet service - -### Full node on the main Ethereum network - -By far the most common scenario is people wanting to simply interact with the Ethereum -network: create accounts; transfer funds; deploy and interact with contracts. For this -particular use-case the user doesn't care about years-old historical data, so we can -sync quickly to the current state of the network. To do so: - -```shell -$ geth console -``` - -This command will: - * Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag), - causing it to download more data in exchange for avoiding processing the entire history - of the Ethereum network, which is very CPU intensive. - * Start up `geth`'s built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interface/javascript-console), - (via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md) - (note: the `web3` version bundled within `geth` is very old, and not up to date with official docs), - as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/rpc/server). - This tool is optional and if you leave it out you can always attach to an already running - `geth` instance with `geth attach`. - -### A Full node on the Görli test network - -Transitioning towards developers, if you'd like to play around with creating Ethereum -contracts, you almost certainly would like to do that without any real money involved until -you get the hang of the entire system. In other words, instead of attaching to the main -network, you want to join the **test** network with your node, which is fully equivalent to -the main network, but with play-Ether only. - -```shell -$ geth --goerli console -``` - -The `console` subcommand has the exact same meaning as above and they are equally -useful on the testnet too. Please, see above for their explanations if you've skipped here. - -Specifying the `--goerli` flag, however, will reconfigure your `geth` instance a bit: - - * Instead of connecting the main Ethereum network, the client will connect to the Görli - test network, which uses different P2P bootnodes, different network IDs and genesis - states. - * Instead of using the default data directory (`~/.ethereum` on Linux for example), `geth` - will nest itself one level deeper into a `goerli` subfolder (`~/.ethereum/goerli` on - Linux). Note, on OSX and Linux this also means that attaching to a running testnet node - requires the use of a custom endpoint since `geth attach` will try to attach to a - production node endpoint by default, e.g., - `geth attach /goerli/geth.ipc`. Windows users are not affected by - this. - -*Note: Although there are some internal protective measures to prevent transactions from -crossing over between the main network and test network, you should make sure to always -use separate accounts for play-money and real-money. Unless you manually move -accounts, `geth` will by default correctly separate the two networks and will not make any -accounts available between them.* - -### Full node on the Rinkeby test network - -Go Ethereum also supports connecting to the older proof-of-authority based test network -called [*Rinkeby*](https://www.rinkeby.io) which is operated by members of the community. - -```shell -$ geth --rinkeby console -``` - -### Full node on the Ropsten test network - -In addition to Görli and Rinkeby, Geth also supports the ancient Ropsten testnet. The -Ropsten test network is based on the Ethash proof-of-work consensus algorithm. As such, -it has certain extra overhead and is more susceptible to reorganization attacks due to the -network's low difficulty/security. +## How it works -```shell -$ geth --ropsten console -``` - -*Note: Older Geth configurations store the Ropsten database in the `testnet` subdirectory.* +Builder API has two hooks into geth: +* On forkchoice update, changing the payload attributes feeRecipient to the one registered for next slot's validator +* On new sealed block, consuming the block as the next slot's proposed payload -### Configuration +## Limitations -As an alternative to passing the numerous flags to the `geth` binary, you can also pass a -configuration file via: +* Blocks are only built on forkchoice update call from beacon node +* Only works post-Bellatrix, fork version is static +* Does not accept external blocks +* Does not have payload cache, only the latest block is available -```shell -$ geth --config /path/to/your_config.toml -``` +## Usage -To get an idea how the file should look like you can use the `dumpconfig` subcommand to -export your existing configuration: +Configure geth for your network, it will become the block builder. -```shell -$ geth --your-favourite-flags dumpconfig +Builder API options: ``` - -*Note: This works only with `geth` v1.6.0 and above.* - -#### Docker quick start - -One of the quickest ways to get Ethereum up and running on your machine is by using -Docker: - -```shell -docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \ - -p 8545:8545 -p 30303:30303 \ - ethereum/client-go +$ geth --help +BUILDER API OPTIONS: + --builder.validator_checks Enable the validator checks + --builder.secret_key value Builder API key used for signing headers (default: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11") [$BUILDER_SECRET_KEY] + --builder.listen_addr value Listening address for builder endpoint (default: ":28545") [$BUILDER_LISTEN_ADDR] + --builder.genesis_fork_version value Gensis fork version (default: "0x02000000") [$BUILDER_GENESIS_FORK_VERSION] + --builder.bellatrix_fork_version value Bellatrix fork version (default: "0x02000000") [$BUILDER_BELLATRIX_FORK_VERSION] + --builder.genesis_validators_root value Genesis validators root of the network (static). For kiln use 0x99b09fcd43e5905236c370f184056bec6e6638cfc31a323b304fc4aa789cb4ad (default: "0x0000000000000000000000000000000000000000000000000000000000000000") [$BUILDER_GENESIS_VALIDATORS_ROOT] + --builder.beacon_endpoint value Beacon endpoint to connect to for beacon chain data (default: "http://127.0.0.1:5052") [$BUILDER_BEACON_ENDPOINT] ``` - -This will start `geth` in snap-sync mode with a DB memory allowance of 1GB just as the -above command does. It will also create a persistent volume in your home directory for -saving your blockchain as well as map the default ports. There is also an `alpine` tag -available for a slim version of the image. - -Do not forget `--http.addr 0.0.0.0`, if you want to access RPC from other containers -and/or hosts. By default, `geth` binds to the local interface and RPC endpoints are not -accessible from the outside. - -### Programmatically interfacing `geth` nodes - -As a developer, sooner rather than later you'll want to start interacting with `geth` and the -Ethereum network via your own programs and not manually through the console. To aid -this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/) -and [`geth` specific APIs](https://geth.ethereum.org/docs/rpc/server)). -These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based -platforms, and named pipes on Windows). - -The IPC interface is enabled by default and exposes all the APIs supported by `geth`, -whereas the HTTP and WS interfaces need to manually be enabled and only expose a -subset of APIs due to security reasons. These can be turned on/off and configured as -you'd expect. - -HTTP based JSON-RPC API options: - - * `--http` Enable the HTTP-RPC server - * `--http.addr` HTTP-RPC server listening interface (default: `localhost`) - * `--http.port` HTTP-RPC server listening port (default: `8545`) - * `--http.api` API's offered over the HTTP-RPC interface (default: `eth,net,web3`) - * `--http.corsdomain` Comma separated list of domains from which to accept cross origin requests (browser enforced) - * `--ws` Enable the WS-RPC server - * `--ws.addr` WS-RPC server listening interface (default: `localhost`) - * `--ws.port` WS-RPC server listening port (default: `8546`) - * `--ws.api` API's offered over the WS-RPC interface (default: `eth,net,web3`) - * `--ws.origins` Origins from which to accept websockets requests - * `--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) - -You'll need to use your own programming environments' capabilities (libraries, tools, etc) to -connect via HTTP, WS or IPC to a `geth` node configured with the above flags and you'll -need to speak [JSON-RPC](https://www.jsonrpc.org/specification) on all transports. You -can reuse the same connection for multiple requests! - -**Note: Please understand the security implications of opening up an HTTP/WS based -transport before doing so! Hackers on the internet are actively trying to subvert -Ethereum nodes with exposed APIs! Further, all browser tabs can access locally -running web servers, so malicious web pages could try to subvert locally available -APIs!** - -### Operating a private network - -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. - -#### Defining the private genesis state - -First, you'll need to create the genesis state of your networks, which all nodes need to be -aware of and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`): - -```json -{ - "config": { - "chainId": , - "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 -$ bootnode --genkey=boot.key -$ bootnode --nodekey=boot.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 also use a full-fledged `geth` node as a bootnode, but it's the less -recommended way.* - -#### Starting up your member nodes - -With the bootnode operational and externally reachable (you can try -`telnet ` 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= -``` - -*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 - -Mining on the public Ethereum network is a complex task as it's only feasible using GPUs, -requiring an OpenCL or CUDA enabled `ethminer` instance. For information on such a -setup, please consult the [EtherMining subreddit](https://www.reddit.com/r/EtherMining/) -and the [ethminer](https://github.com/ethereum-mining/ethminer) repository. - -In a private network setting, however 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 --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 - -Thank you for considering to help out with the source code! We welcome contributions -from anyone on the internet, and are grateful for even the smallest of fixes! - -If you'd like to contribute to go-ethereum, please fork, fix, commit and send a pull request -for the maintainers to review and merge into the main code base. If you wish to submit -more complex changes though, please check up with the core devs first on [our Discord Server](https://discord.gg/invite/nthXNEv) -to ensure those changes are in line with the general philosophy of the project and/or get -some early feedback which can make both your efforts much lighter as well as our review -and merge procedures quick and simple. - -Please make sure your contributions adhere to our coding guidelines: - - * Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) - guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). - * Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) - guidelines. - * Pull requests need to be based on and opened against the `master` branch. - * Commit messages should be prefixed with the package(s) they modify. - * E.g. "eth, rpc: make trace configs optional" - -Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/devguide) -for more details on configuring your environment, managing project dependencies, and -testing procedures. - -## License - -The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the -[GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html), -also included in our repository in the `COPYING.LESSER` file. - -The go-ethereum binaries (i.e. all code inside of the `cmd` directory) is licensed under the -[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html), also -included in our repository in the `COPYING` file. diff --git a/README.original.md b/README.original.md new file mode 100644 index 0000000000..b20eb5b748 --- /dev/null +++ b/README.original.md @@ -0,0 +1,379 @@ +## Go Ethereum + +Official Golang implementation of the Ethereum protocol. + +[![API Reference]( +https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667 +)](https://pkg.go.dev/github.com/ethereum/go-ethereum?tab=doc) +[![Go Report Card](https://goreportcard.com/badge/github.com/ethereum/go-ethereum)](https://goreportcard.com/report/github.com/ethereum/go-ethereum) +[![Travis](https://travis-ci.com/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.com/ethereum/go-ethereum) +[![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.gg/nthXNEv) + +Automated builds are available for stable releases and the unstable master branch. Binary +archives are published at https://geth.ethereum.org/downloads/. + +## Building the source + +For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/install-and-build/installing-geth). + +Building `geth` requires both a Go (version 1.16 or later) and a C compiler. You can install +them using your favourite package manager. Once the dependencies are installed, run + +```shell +make geth +``` + +or, to build the full suite of utilities: + +```shell +make all +``` + +## Executables + +The go-ethereum project comes with several wrappers/executables found in the `cmd` +directory. + +| Command | Description | +| :-----------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/interface/command-line-options) for command line options. | +| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. | +| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. | +| `abigen` | Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/dapp/native-bindings) page for details. | +| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. | +| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). | +| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). | +| `puppeth` | a CLI wizard that aids in creating a new Ethereum network. | + +## Running `geth` + +Going through all the possible command line flags is out of scope here (please consult our +[CLI Wiki page](https://geth.ethereum.org/docs/interface/command-line-options)), +but we've enumerated a few common parameter combos to get you up to speed quickly +on how you can run your own `geth` instance. + +### Hardware Requirements + +Minimum: + +* CPU with 2+ cores +* 4GB RAM +* 1TB free storage space to sync the Mainnet +* 8 MBit/sec download Internet service + +Recommended: + +* Fast CPU with 4+ cores +* 16GB+ RAM +* High Performance SSD with at least 1TB free space +* 25+ MBit/sec download Internet service + +### Full node on the main Ethereum network + +By far the most common scenario is people wanting to simply interact with the Ethereum +network: create accounts; transfer funds; deploy and interact with contracts. For this +particular use-case the user doesn't care about years-old historical data, so we can +sync quickly to the current state of the network. To do so: + +```shell +$ geth console +``` + +This command will: + * Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag), + causing it to download more data in exchange for avoiding processing the entire history + of the Ethereum network, which is very CPU intensive. + * Start up `geth`'s built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interface/javascript-console), + (via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md) + (note: the `web3` version bundled within `geth` is very old, and not up to date with official docs), + as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/rpc/server). + This tool is optional and if you leave it out you can always attach to an already running + `geth` instance with `geth attach`. + +### A Full node on the Görli test network + +Transitioning towards developers, if you'd like to play around with creating Ethereum +contracts, you almost certainly would like to do that without any real money involved until +you get the hang of the entire system. In other words, instead of attaching to the main +network, you want to join the **test** network with your node, which is fully equivalent to +the main network, but with play-Ether only. + +```shell +$ geth --goerli console +``` + +The `console` subcommand has the exact same meaning as above and they are equally +useful on the testnet too. Please, see above for their explanations if you've skipped here. + +Specifying the `--goerli` flag, however, will reconfigure your `geth` instance a bit: + + * Instead of connecting the main Ethereum network, the client will connect to the Görli + test network, which uses different P2P bootnodes, different network IDs and genesis + states. + * Instead of using the default data directory (`~/.ethereum` on Linux for example), `geth` + will nest itself one level deeper into a `goerli` subfolder (`~/.ethereum/goerli` on + Linux). Note, on OSX and Linux this also means that attaching to a running testnet node + requires the use of a custom endpoint since `geth attach` will try to attach to a + production node endpoint by default, e.g., + `geth attach /goerli/geth.ipc`. Windows users are not affected by + this. + +*Note: Although there are some internal protective measures to prevent transactions from +crossing over between the main network and test network, you should make sure to always +use separate accounts for play-money and real-money. Unless you manually move +accounts, `geth` will by default correctly separate the two networks and will not make any +accounts available between them.* + +### Full node on the Rinkeby test network + +Go Ethereum also supports connecting to the older proof-of-authority based test network +called [*Rinkeby*](https://www.rinkeby.io) which is operated by members of the community. + +```shell +$ geth --rinkeby console +``` + +### Full node on the Ropsten test network + +In addition to Görli and Rinkeby, Geth also supports the ancient Ropsten testnet. The +Ropsten test network is based on the Ethash proof-of-work consensus algorithm. As such, +it has certain extra overhead and is more susceptible to reorganization attacks due to the +network's low difficulty/security. + +```shell +$ geth --ropsten console +``` + +*Note: Older Geth configurations store the Ropsten database in the `testnet` subdirectory.* + +### Configuration + +As an alternative to passing the numerous flags to the `geth` binary, you can also pass a +configuration file via: + +```shell +$ geth --config /path/to/your_config.toml +``` + +To get an idea how the file should look like you can use the `dumpconfig` subcommand to +export your existing configuration: + +```shell +$ geth --your-favourite-flags dumpconfig +``` + +*Note: This works only with `geth` v1.6.0 and above.* + +#### Docker quick start + +One of the quickest ways to get Ethereum up and running on your machine is by using +Docker: + +```shell +docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \ + -p 8545:8545 -p 30303:30303 \ + ethereum/client-go +``` + +This will start `geth` in snap-sync mode with a DB memory allowance of 1GB just as the +above command does. It will also create a persistent volume in your home directory for +saving your blockchain as well as map the default ports. There is also an `alpine` tag +available for a slim version of the image. + +Do not forget `--http.addr 0.0.0.0`, if you want to access RPC from other containers +and/or hosts. By default, `geth` binds to the local interface and RPC endpoints are not +accessible from the outside. + +### Programmatically interfacing `geth` nodes + +As a developer, sooner rather than later you'll want to start interacting with `geth` and the +Ethereum network via your own programs and not manually through the console. To aid +this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/) +and [`geth` specific APIs](https://geth.ethereum.org/docs/rpc/server)). +These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based +platforms, and named pipes on Windows). + +The IPC interface is enabled by default and exposes all the APIs supported by `geth`, +whereas the HTTP and WS interfaces need to manually be enabled and only expose a +subset of APIs due to security reasons. These can be turned on/off and configured as +you'd expect. + +HTTP based JSON-RPC API options: + + * `--http` Enable the HTTP-RPC server + * `--http.addr` HTTP-RPC server listening interface (default: `localhost`) + * `--http.port` HTTP-RPC server listening port (default: `8545`) + * `--http.api` API's offered over the HTTP-RPC interface (default: `eth,net,web3`) + * `--http.corsdomain` Comma separated list of domains from which to accept cross origin requests (browser enforced) + * `--ws` Enable the WS-RPC server + * `--ws.addr` WS-RPC server listening interface (default: `localhost`) + * `--ws.port` WS-RPC server listening port (default: `8546`) + * `--ws.api` API's offered over the WS-RPC interface (default: `eth,net,web3`) + * `--ws.origins` Origins from which to accept websockets requests + * `--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) + +You'll need to use your own programming environments' capabilities (libraries, tools, etc) to +connect via HTTP, WS or IPC to a `geth` node configured with the above flags and you'll +need to speak [JSON-RPC](https://www.jsonrpc.org/specification) on all transports. You +can reuse the same connection for multiple requests! + +**Note: Please understand the security implications of opening up an HTTP/WS based +transport before doing so! Hackers on the internet are actively trying to subvert +Ethereum nodes with exposed APIs! Further, all browser tabs can access locally +running web servers, so malicious web pages could try to subvert locally available +APIs!** + +### Operating a private network + +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. + +#### Defining the private genesis state + +First, you'll need to create the genesis state of your networks, which all nodes need to be +aware of and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`): + +```json +{ + "config": { + "chainId": , + "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 +$ bootnode --genkey=boot.key +$ bootnode --nodekey=boot.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 also use a full-fledged `geth` node as a bootnode, but it's the less +recommended way.* + +#### Starting up your member nodes + +With the bootnode operational and externally reachable (you can try +`telnet ` 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= +``` + +*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 + +Mining on the public Ethereum network is a complex task as it's only feasible using GPUs, +requiring an OpenCL or CUDA enabled `ethminer` instance. For information on such a +setup, please consult the [EtherMining subreddit](https://www.reddit.com/r/EtherMining/) +and the [ethminer](https://github.com/ethereum-mining/ethminer) repository. + +In a private network setting, however 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 --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 + +Thank you for considering to help out with the source code! We welcome contributions +from anyone on the internet, and are grateful for even the smallest of fixes! + +If you'd like to contribute to go-ethereum, please fork, fix, commit and send a pull request +for the maintainers to review and merge into the main code base. If you wish to submit +more complex changes though, please check up with the core devs first on [our Discord Server](https://discord.gg/invite/nthXNEv) +to ensure those changes are in line with the general philosophy of the project and/or get +some early feedback which can make both your efforts much lighter as well as our review +and merge procedures quick and simple. + +Please make sure your contributions adhere to our coding guidelines: + + * Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) + guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). + * Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) + guidelines. + * Pull requests need to be based on and opened against the `master` branch. + * Commit messages should be prefixed with the package(s) they modify. + * E.g. "eth, rpc: make trace configs optional" + +Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/devguide) +for more details on configuring your environment, managing project dependencies, and +testing procedures. + +## License + +The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the +[GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html), +also included in our repository in the `COPYING.LESSER` file. + +The go-ethereum binaries (i.e. all code inside of the `cmd` directory) is licensed under the +[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html), also +included in our repository in the `COPYING` file. diff --git a/builder/backend.go b/builder/backend.go new file mode 100644 index 0000000000..5473e280dc --- /dev/null +++ b/builder/backend.go @@ -0,0 +1,436 @@ +package builder + +import ( + "bytes" + "encoding/json" + "fmt" + "html/template" + "math/big" + "net/http" + _ "os" + "strconv" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/beacon" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/trie" + "github.com/gorilla/mux" + + "github.com/flashbots/go-boost-utils/bls" + boostTypes "github.com/flashbots/go-boost-utils/types" +) + +type PubkeyHex string + +type ValidatorData struct { + FeeRecipient boostTypes.Address `json:"feeRecipient"` + GasLimit uint64 `json:"gasLimit"` + Timestamp uint64 `json:"timestamp"` +} + +type IBeaconClient interface { + isValidator(pubkey PubkeyHex) bool + getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) + onForkchoiceUpdate() (PubkeyHex, error) +} + +type Backend struct { + beaconClient IBeaconClient + + builderSecretKey *bls.SecretKey + builderPublicKey boostTypes.PublicKey + serializedBuilderPoolPubkey hexutil.Bytes + builderSigningDomain boostTypes.Domain + proposerSigningDomain boostTypes.Domain + enableBeaconChecks bool + + validatorsLock sync.RWMutex + validators map[PubkeyHex]ValidatorData + + bestDataLock sync.Mutex + bestHeader *boostTypes.ExecutionPayloadHeader + bestPayload *boostTypes.ExecutionPayload + profit *big.Int + + indexTemplate *template.Template +} + +func NewBackend(sk *bls.SecretKey, bc IBeaconClient, builderSigningDomain boostTypes.Domain, proposerSigningDomain boostTypes.Domain, enableBeaconChecks bool) *Backend { + pkBytes := bls.PublicKeyFromSecretKey(sk).Compress() + pk := boostTypes.PublicKey{} + pk.FromSlice(pkBytes) + + _, err := bc.onForkchoiceUpdate() + if err != nil { + log.Error("could not initialize beacon client", "err", err) + } + + indexTemplate, err := parseIndexTemplate() + if err != nil { + log.Error("could not parse index template", "err", err) + indexTemplate = nil + } + return &Backend{ + beaconClient: bc, + builderSecretKey: sk, + builderPublicKey: pk, + serializedBuilderPoolPubkey: pkBytes, + + builderSigningDomain: builderSigningDomain, + proposerSigningDomain: proposerSigningDomain, + enableBeaconChecks: enableBeaconChecks, + validators: make(map[PubkeyHex]ValidatorData), + indexTemplate: indexTemplate, + } +} + +func (b *Backend) handleIndex(w http.ResponseWriter, req *http.Request) { + if b.indexTemplate == nil { + http.Error(w, "not available", http.StatusInternalServerError) + } + + b.validatorsLock.RLock() + noValidators := len(b.validators) + b.validatorsLock.RUnlock() + + header := b.bestHeader + headerData, err := json.MarshalIndent(header, "", " ") + if err != nil { + headerData = []byte{} + } + + payload := b.bestPayload + payloadData, err := json.MarshalIndent(payload, "", " ") + if err != nil { + payloadData = []byte{} + } + + statusData := struct { + NoValidators int + Header string + Blocks string + }{noValidators, string(headerData), string(payloadData)} + + if err := b.indexTemplate.Execute(w, statusData); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} + +func (b *Backend) handleStatus(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(http.StatusOK) +} + +type httpErrorResp struct { + Code int `json:"code"` + Message string `json:"message"` +} + +func respondError(w http.ResponseWriter, code int, message string) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + if err := json.NewEncoder(w).Encode(httpErrorResp{code, message}); err != nil { + http.Error(w, message, code) + } +} + +func (b *Backend) handleRegisterValidator(w http.ResponseWriter, req *http.Request) { + payload := []boostTypes.SignedValidatorRegistration{} + if err := json.NewDecoder(req.Body).Decode(&payload); err != nil { + log.Error("could not decode payload", "err", err) + respondError(w, http.StatusBadRequest, "invalid payload") + return + } + + for _, registerRequest := range payload { + if len(registerRequest.Message.Pubkey) != 48 { + respondError(w, http.StatusBadRequest, "invalid pubkey") + return + } + + if len(registerRequest.Signature) != 96 { + respondError(w, http.StatusBadRequest, "invalid signature") + return + } + + ok, err := boostTypes.VerifySignature(registerRequest.Message, b.builderSigningDomain, registerRequest.Message.Pubkey[:], registerRequest.Signature[:]) + if !ok || err != nil { + log.Error("error verifying signature", "err", err) + respondError(w, http.StatusBadRequest, "invalid signature") + return + } + + // Do not check timestamp before signature, as it would leak validator data + if registerRequest.Message.Timestamp > uint64(time.Now().Add(10*time.Second).Unix()) { + respondError(w, http.StatusBadRequest, "invalid payload") + return + } + } + + for _, registerRequest := range payload { + pubkeyHex := PubkeyHex(registerRequest.Message.Pubkey.String()) + if !b.beaconClient.isValidator(pubkeyHex) { + respondError(w, http.StatusBadRequest, "not a validator") + return + } + } + + b.validatorsLock.Lock() + defer b.validatorsLock.Unlock() + + for _, registerRequest := range payload { + pubkeyHex := PubkeyHex(registerRequest.Message.Pubkey.String()) + if previousValidatorData, ok := b.validators[pubkeyHex]; ok { + if registerRequest.Message.Timestamp <= previousValidatorData.Timestamp { + respondError(w, http.StatusBadRequest, "invalid timestamp") + return + } + } + } + + for _, registerRequest := range payload { + pubkeyHex := PubkeyHex(registerRequest.Message.Pubkey.String()) + b.validators[pubkeyHex] = ValidatorData{ + FeeRecipient: registerRequest.Message.FeeRecipient, + GasLimit: registerRequest.Message.GasLimit, + Timestamp: registerRequest.Message.Timestamp, + } + + log.Info("registered validator", "pubkey", pubkeyHex, "data", b.validators[pubkeyHex]) + } + + w.WriteHeader(http.StatusOK) +} + +func (b *Backend) handleGetHeader(w http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + slot, err := strconv.Atoi(vars["slot"]) + if err != nil { + respondError(w, http.StatusBadRequest, "incorrect slot") + return + } + parentHashHex := vars["parent_hash"] + pubkeyHex := PubkeyHex(vars["pubkey"]) + + b.validatorsLock.RLock() + if _, ok := b.validators[pubkeyHex]; !ok { + log.Error("missing validator", "validators", b.validators, "provided", pubkeyHex) + b.validatorsLock.RUnlock() + respondError(w, http.StatusBadRequest, "unknown validator") + return + } + b.validatorsLock.RUnlock() + + // Do not validate slot separately, it will create a race between slot update and proposer key + if nextSlotProposer, err := b.beaconClient.getProposerForNextSlot(uint64(slot)); err != nil || nextSlotProposer != pubkeyHex { + log.Error("getHeader requested for public key other than next slots proposer", "requested", pubkeyHex, "expected", nextSlotProposer) + if b.enableBeaconChecks { + respondError(w, http.StatusBadRequest, "unknown validator") + return + } + } + + b.bestDataLock.Lock() + bestHeader := b.bestHeader + profit := b.profit + b.bestDataLock.Unlock() + + if bestHeader == nil || bestHeader.ParentHash.String() != parentHashHex { + respondError(w, http.StatusBadRequest, "unknown payload") + return + } + + bid := boostTypes.BuilderBid{ + Header: bestHeader, + Value: [32]byte(common.BytesToHash(profit.Bytes())), + Pubkey: b.builderPublicKey, + } + signature, err := boostTypes.SignMessage(&bid, b.builderSigningDomain, b.builderSecretKey) + if err != nil { + respondError(w, http.StatusInternalServerError, "internal server error") + return + } + + response := &boostTypes.GetHeaderResponse{ + Version: "bellatrix", + Data: &boostTypes.SignedBuilderBid{Message: &bid, Signature: signature}, + } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(response); err != nil { + respondError(w, http.StatusInternalServerError, "internal server error") + return + } +} + +func (b *Backend) handleGetPayload(w http.ResponseWriter, req *http.Request) { + payload := new(boostTypes.SignedBlindedBeaconBlock) + if err := json.NewDecoder(req.Body).Decode(&payload); err != nil { + respondError(w, http.StatusBadRequest, "invalid payload") + return + } + + if len(payload.Signature) != 96 { + respondError(w, http.StatusBadRequest, "invalid signature") + return + } + + nextSlotProposerPubkeyHex, err := b.beaconClient.getProposerForNextSlot(payload.Message.Slot) + if err != nil { + if b.enableBeaconChecks { + respondError(w, http.StatusBadRequest, "unknown validator") + return + } + } + + nextSlotProposerPubkeyBytes, err := hexutil.Decode(string(nextSlotProposerPubkeyHex)) + if err != nil { + if b.enableBeaconChecks { + respondError(w, http.StatusBadRequest, "unknown validator") + return + } + } + + ok, err := boostTypes.VerifySignature(payload.Message, b.proposerSigningDomain, nextSlotProposerPubkeyBytes[:], payload.Signature[:]) + if !ok || err != nil { + if b.enableBeaconChecks { + respondError(w, http.StatusBadRequest, "invalid signature") + return + } + } + + b.bestDataLock.Lock() + bestHeader := b.bestHeader + bestPayload := b.bestPayload + b.bestDataLock.Unlock() + + if bestHeader == nil || bestPayload == nil { + respondError(w, http.StatusInternalServerError, "no payloads") + return + } + + if !ExecutionPayloadHeaderEqual(bestHeader, payload.Message.Body.ExecutionPayloadHeader) { + respondError(w, http.StatusBadRequest, "unknown payload") + return + } + + response := boostTypes.GetPayloadResponse{ + Version: "bellatrix", + Data: bestPayload, + } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(response); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + respondError(w, http.StatusInternalServerError, "internal server error") + return + } +} + +func (b *Backend) onForkchoice(payloadAttributes *beacon.PayloadAttributesV1) { + dataJson, err := json.Marshal(payloadAttributes) + if err == nil { + log.Info("FCU", "data", string(dataJson)) + } + // if payloadAttributes.SuggestedFeeRecipient == common.Address{} + pubkeyHex, err := b.beaconClient.onForkchoiceUpdate() + if err != nil { + return + } + + if payloadAttributes != nil { + b.validatorsLock.RLock() + vd, found := b.validators[pubkeyHex] + if found { + payloadAttributes.SuggestedFeeRecipient = [20]byte(vd.FeeRecipient) + payloadAttributes.GasLimit = vd.GasLimit + } + b.validatorsLock.RUnlock() + } +} + +func (b *Backend) newSealedBlock(data *beacon.ExecutableDataV1, block *types.Block) { + dataJson, err := json.Marshal(data) + if err == nil { + log.Info("newSealedBlock", "data", string(dataJson)) + } + payload := executableDataToExecutionPayload(data) + payloadHeader, err := payloadToPayloadHeader(payload) + if err != nil { + log.Error("could not convert payload to header", "err", err) + return + } + + b.bestDataLock.Lock() + b.bestHeader = payloadHeader + b.bestPayload = payload + b.profit = new(big.Int).Set(block.Profit) + b.bestDataLock.Unlock() +} + +func decodeTransactions(enc []hexutil.Bytes) ([]*types.Transaction, error) { + var txs = make([]*types.Transaction, len(enc)) + for i, encTx := range enc { + var tx types.Transaction + if err := tx.UnmarshalBinary(encTx); err != nil { + return nil, fmt.Errorf("invalid transaction %d: %v", i, err) + } + txs[i] = &tx + } + return txs, nil +} + +func payloadToPayloadHeader(p *boostTypes.ExecutionPayload) (*boostTypes.ExecutionPayloadHeader, error) { + txs, err := decodeTransactions(p.Transactions) + if err != nil { + return nil, err + } + return &boostTypes.ExecutionPayloadHeader{ + ParentHash: p.ParentHash, + FeeRecipient: p.FeeRecipient, + StateRoot: p.StateRoot, + ReceiptsRoot: p.ReceiptsRoot, + LogsBloom: p.LogsBloom, + Random: p.Random, + BlockNumber: p.BlockNumber, + GasLimit: p.GasLimit, + GasUsed: p.GasUsed, + Timestamp: p.Timestamp, + ExtraData: []byte(p.ExtraData), + BaseFeePerGas: p.BaseFeePerGas, + BlockHash: p.BlockHash, + TransactionsRoot: [32]byte(types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil))), + }, nil +} + +func executableDataToExecutionPayload(data *beacon.ExecutableDataV1) *boostTypes.ExecutionPayload { + transactionData := make([]hexutil.Bytes, len(data.Transactions)) + for i, tx := range data.Transactions { + transactionData[i] = hexutil.Bytes(tx) + } + logsBloom := boostTypes.Bloom{} + logsBloom.FromSlice(data.LogsBloom) + return &boostTypes.ExecutionPayload{ + ParentHash: [32]byte(data.ParentHash), + FeeRecipient: [20]byte(data.FeeRecipient), + StateRoot: [32]byte(data.StateRoot), + ReceiptsRoot: [32]byte(data.ReceiptsRoot), + LogsBloom: logsBloom, + Random: [32]byte(data.Random), + BlockNumber: data.Number, + GasLimit: data.GasLimit, + GasUsed: data.GasUsed, + Timestamp: data.Timestamp, + ExtraData: data.ExtraData, + BaseFeePerGas: [32]byte(common.BytesToHash(data.BaseFeePerGas.Bytes())), + BlockHash: [32]byte(data.BlockHash), + Transactions: transactionData, + } +} + +func ExecutionPayloadHeaderEqual(l *boostTypes.ExecutionPayloadHeader, r *boostTypes.ExecutionPayloadHeader) bool { + return l.ParentHash == r.ParentHash && l.FeeRecipient == r.FeeRecipient && l.StateRoot == r.StateRoot && l.ReceiptsRoot == r.ReceiptsRoot && l.LogsBloom == r.LogsBloom && l.Random == r.Random && l.BlockNumber == r.BlockNumber && l.GasLimit == r.GasLimit && l.GasUsed == r.GasUsed && l.Timestamp == r.Timestamp && l.BaseFeePerGas == r.BaseFeePerGas && bytes.Equal(l.ExtraData, r.ExtraData) && l.BlockHash == r.BlockHash && l.TransactionsRoot == r.TransactionsRoot +} diff --git a/builder/backend_test.go b/builder/backend_test.go new file mode 100644 index 0000000000..dbd56d7c35 --- /dev/null +++ b/builder/backend_test.go @@ -0,0 +1,233 @@ +package builder + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/beacon" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/flashbots/go-boost-utils/bls" + boostTypes "github.com/flashbots/go-boost-utils/types" + "github.com/stretchr/testify/require" +) + +func newTestBackend(t *testing.T) (*Backend, *ValidatorPrivateData) { + validator := NewRandomValidator() + sk, _ := bls.GenerateRandomSecretKey() + bDomain := boostTypes.ComputeDomain(boostTypes.DomainTypeAppBuilder, [4]byte{0x02, 0x0, 0x0, 0x0}, boostTypes.Hash{}) + genesisValidatorsRoot := boostTypes.Hash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")) + cDomain := boostTypes.ComputeDomain(boostTypes.DomainTypeBeaconProposer, [4]byte{0x02, 0x0, 0x0, 0x0}, genesisValidatorsRoot) + backend := NewBackend(sk, &testBeaconClient{validator}, bDomain, cDomain, true) + // service := NewService("127.0.0.1:31545", backend) + + return backend, validator +} + +func testRequest(t *testing.T, backend *Backend, method string, path string, payload any) *httptest.ResponseRecorder { + var req *http.Request + var err error + + if payload == nil { + req, err = http.NewRequest(method, path, nil) + } else { + payloadBytes, err2 := json.Marshal(payload) + require.NoError(t, err2) + req, err = http.NewRequest(method, path, bytes.NewReader(payloadBytes)) + } + + require.NoError(t, err) + rr := httptest.NewRecorder() + getRouter(backend).ServeHTTP(rr, req) + return rr +} + +func TestValidatorRegistration(t *testing.T) { + backend, _ := newTestBackend(t) + log.Error("rsk", "sk", hexutil.Encode(backend.builderSecretKey.Serialize())) + + v := NewRandomValidator() + payload, err := prepareRegistrationMessage(t, backend.builderSigningDomain, v) + require.NoError(t, err) + + rr := testRequest(t, backend, "POST", "/eth/v1/builder/validators", payload) + require.Equal(t, http.StatusOK, rr.Code) + require.Contains(t, backend.validators, PubkeyHex(v.Pk.String())) + require.Equal(t, ValidatorData{FeeRecipient: payload[0].Message.FeeRecipient, GasLimit: payload[0].Message.GasLimit, Timestamp: payload[0].Message.Timestamp}, backend.validators[PubkeyHex(v.Pk.String())]) + + rr = testRequest(t, backend, "POST", "/eth/v1/builder/validators", payload) + require.Equal(t, http.StatusBadRequest, rr.Code) + require.Equal(t, `{"code":400,"message":"invalid timestamp"}`+"\n", rr.Body.String()) + + payload[0].Message.Timestamp += 1 + // Invalid signature + payload[0].Signature[len(payload[0].Signature)-1] = 0x00 + rr = testRequest(t, backend, "POST", "/eth/v1/builder/validators", payload) + require.Equal(t, http.StatusBadRequest, rr.Code) + require.Equal(t, `{"code":400,"message":"invalid signature"}`+"\n", rr.Body.String()) + + // TODO: cover all errors +} + +func prepareRegistrationMessage(t *testing.T, domain boostTypes.Domain, v *ValidatorPrivateData) ([]boostTypes.SignedValidatorRegistration, error) { + var pubkey boostTypes.PublicKey + pubkey.FromSlice(v.Pk) + require.Equal(t, []byte(v.Pk), pubkey[:]) + + msg := boostTypes.RegisterValidatorRequestMessage{ + FeeRecipient: boostTypes.Address{0x42}, + GasLimit: 15_000_000, + Timestamp: uint64(time.Now().Unix()), + Pubkey: pubkey, + } + + signature, err := v.Sign(&msg, domain) + require.NoError(t, err) + + return []boostTypes.SignedValidatorRegistration{{ + Message: &msg, + Signature: signature, + }}, nil +} + +func registerValidator(t *testing.T, v *ValidatorPrivateData, backend *Backend) { + payload, err := prepareRegistrationMessage(t, backend.builderSigningDomain, v) + require.NoError(t, err) + + log.Info("Registering", "payload", payload[0].Message) + rr := testRequest(t, backend, "POST", "/eth/v1/builder/validators", payload) + require.Equal(t, http.StatusOK, rr.Code) + require.Contains(t, backend.validators, PubkeyHex(v.Pk.String())) + require.Equal(t, ValidatorData{FeeRecipient: payload[0].Message.FeeRecipient, GasLimit: payload[0].Message.GasLimit, Timestamp: payload[0].Message.Timestamp}, backend.validators[PubkeyHex(v.Pk.String())]) +} + +func TestGetHeader(t *testing.T) { + backend, validator := newTestBackend(t) + + forkchoiceData := &beacon.ExecutableDataV1{ + ParentHash: common.HexToHash("0xafafafa"), + FeeRecipient: common.Address{0x01}, + BlockHash: common.HexToHash("0xbfbfbfb"), + BaseFeePerGas: big.NewInt(12), + ExtraData: []byte{}, + } + forkchoiceBlock := &types.Block{ + Profit: big.NewInt(10), + } + + path := fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), validator.Pk.String()) + rr := testRequest(t, backend, "GET", path, nil) + require.Equal(t, `{"code":400,"message":"unknown validator"}`+"\n", rr.Body.String()) + + registerValidator(t, validator, backend) + + rr = testRequest(t, backend, "GET", path, nil) + require.Equal(t, `{"code":400,"message":"unknown payload"}`+"\n", rr.Body.String()) + + path = fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), NewRandomValidator().Pk.String()) + rr = testRequest(t, backend, "GET", path, nil) + require.Equal(t, `{"code":400,"message":"unknown validator"}`+"\n", rr.Body.String()) + + backend.newSealedBlock(forkchoiceData, forkchoiceBlock) + + path = fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), validator.Pk.String()) + rr = testRequest(t, backend, "GET", path, nil) + require.Equal(t, http.StatusOK, rr.Code) + + bid := new(boostTypes.GetHeaderResponse) + err := json.Unmarshal(rr.Body.Bytes(), bid) + require.NoError(t, err) + + expectedHeader, err := payloadToPayloadHeader(executableDataToExecutionPayload(forkchoiceData)) + require.NoError(t, err) + require.EqualValues(t, &boostTypes.BuilderBid{ + Header: expectedHeader, + Value: [32]byte(common.BytesToHash(forkchoiceBlock.Profit.Bytes())), + Pubkey: backend.builderPublicKey, + }, bid.Data.Message) + + require.Equal(t, forkchoiceData.ParentHash.Bytes(), bid.Data.Message.Header.ParentHash[:], "didn't build on expected parent") + ok, err := boostTypes.VerifySignature(bid.Data.Message, backend.builderSigningDomain, backend.builderPublicKey[:], bid.Data.Signature[:]) + + require.NoError(t, err) + require.True(t, ok) +} + +func TestGetPayload(t *testing.T) { + backend, validator := newTestBackend(t) + + forkchoiceData := &beacon.ExecutableDataV1{ + ParentHash: common.HexToHash("0xafafafa"), + FeeRecipient: common.Address{0x01}, + BlockHash: common.HexToHash("0xbfbfbfb"), + BaseFeePerGas: big.NewInt(12), + ExtraData: []byte{}, + } + forkchoiceBlock := &types.Block{ + Profit: big.NewInt(10), + } + + registerValidator(t, validator, backend) + backend.newSealedBlock(forkchoiceData, forkchoiceBlock) + + path := fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), validator.Pk.String()) + rr := testRequest(t, backend, "GET", path, nil) + require.Equal(t, http.StatusOK, rr.Code) + + bid := new(boostTypes.GetHeaderResponse) + err := json.Unmarshal(rr.Body.Bytes(), bid) + require.NoError(t, err) + + // Create request payload + msg := &boostTypes.BlindedBeaconBlock{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: boostTypes.Root{0x03}, + StateRoot: boostTypes.Root{0x04}, + Body: &boostTypes.BlindedBeaconBlockBody{ + Eth1Data: &boostTypes.Eth1Data{ + DepositRoot: boostTypes.Root{0x05}, + DepositCount: 5, + BlockHash: boostTypes.Hash{0x06}, + }, + SyncAggregate: &boostTypes.SyncAggregate{ + CommitteeBits: boostTypes.CommitteeBits{0x07}, + CommitteeSignature: boostTypes.Signature{0x08}, + }, + ExecutionPayloadHeader: bid.Data.Message.Header, + }, + } + + // TODO: test wrong signing domain + signature, err := validator.Sign(msg, backend.proposerSigningDomain) + require.NoError(t, err) + + // Call getPayload with invalid signature + rr = testRequest(t, backend, "POST", "/eth/v1/builder/blinded_blocks", boostTypes.SignedBlindedBeaconBlock{ + Message: msg, + Signature: boostTypes.Signature{0x09}, + }) + require.Equal(t, http.StatusBadRequest, rr.Code) + require.Equal(t, `{"code":400,"message":"invalid signature"}`+"\n", rr.Body.String()) + + // Call getPayload with correct signature + rr = testRequest(t, backend, "POST", "/eth/v1/builder/blinded_blocks", boostTypes.SignedBlindedBeaconBlock{ + Message: msg, + Signature: signature, + }) + + // Verify getPayload response + require.Equal(t, http.StatusOK, rr.Code) + getPayloadResponse := new(boostTypes.GetPayloadResponse) + err = json.Unmarshal(rr.Body.Bytes(), getPayloadResponse) + require.NoError(t, err) + require.Equal(t, bid.Data.Message.Header.BlockHash, getPayloadResponse.Data.BlockHash) +} diff --git a/builder/beacon_client.go b/builder/beacon_client.go new file mode 100644 index 0000000000..62138c9b05 --- /dev/null +++ b/builder/beacon_client.go @@ -0,0 +1,200 @@ +package builder + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strconv" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" +) + +type testBeaconClient struct { + validator *ValidatorPrivateData +} + +func (b *testBeaconClient) isValidator(pubkey PubkeyHex) bool { + return true +} +func (b *testBeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { + return PubkeyHex(hexutil.Encode(b.validator.Pk)), nil +} +func (b *testBeaconClient) onForkchoiceUpdate() (PubkeyHex, error) { + return PubkeyHex(hexutil.Encode(b.validator.Pk)), nil +} + +type BeaconClient struct { + endpoint string + + mu sync.Mutex + currentEpoch uint64 + currentSlot uint64 + nextSlotProposer PubkeyHex + slotProposerMap map[uint64]PubkeyHex +} + +func NewBeaconClient(endpoint string) *BeaconClient { + return &BeaconClient{ + endpoint: endpoint, + slotProposerMap: make(map[uint64]PubkeyHex), + } +} + +func (b *BeaconClient) isValidator(pubkey PubkeyHex) bool { + return true +} + +func (b *BeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { + /* Only returns proposer if requestedSlot is currentSlot + 1, would be a race otherwise */ + b.mu.Lock() + defer b.mu.Unlock() + + if b.currentSlot+1 != requestedSlot { + return PubkeyHex(""), errors.New("slot out of sync") + } + return b.nextSlotProposer, nil +} + +/* Returns next slot's proposer pubkey */ +// TODO: what happens if no block for previous slot - should still get next slot +func (b *BeaconClient) onForkchoiceUpdate() (PubkeyHex, error) { + b.mu.Lock() + defer b.mu.Unlock() + + currentSlot, err := fetchCurrentSlot(b.endpoint) + if err != nil { + return PubkeyHex(""), err + } + + nextSlot := currentSlot + 1 + + b.currentSlot = currentSlot + nextSlotEpoch := nextSlot / 32 + + if nextSlotEpoch != b.currentEpoch { + // TODO: this should be prepared in advance, possibly just fetch for next epoch in advance + slotProposerMap, err := fetchEpochProposersMap(b.endpoint, nextSlotEpoch) + if err != nil { + return PubkeyHex(""), err + } + + b.currentEpoch = nextSlotEpoch + b.slotProposerMap = slotProposerMap + } + + nextSlotProposer, found := b.slotProposerMap[nextSlot] + if !found { + log.Error("inconsistent proposer mapping", "currentSlot", currentSlot, "slotProposerMap", b.slotProposerMap) + return PubkeyHex(""), errors.New("inconsistent proposer mapping") + } + b.nextSlotProposer = nextSlotProposer + return nextSlotProposer, nil +} + +func fetchCurrentSlot(endpoint string) (uint64, error) { + headerRes := &struct { + Data []struct { + Root common.Hash `json:"root"` + Canonical bool `json:"canonical"` + Header struct { + Message struct { + Slot string `json:"slot"` + ProposerIndex string `json:"proposer_index"` + ParentRoot common.Hash `json:"parent_root"` + StateRoot common.Hash `json:"state_root"` + BodyRoot common.Hash `json:"body_root"` + } `json:"message"` + Signature hexutil.Bytes `json:"signature"` + } `json:"header"` + } `json:"data"` + }{} + + err := fetchBeacon(endpoint+"/eth/v1/beacon/headers", headerRes) + if err != nil { + return uint64(0), err + } + + if len(headerRes.Data) != 1 { + return uint64(0), errors.New("invalid response") + } + + slot, err := strconv.Atoi(headerRes.Data[0].Header.Message.Slot) + if err != nil { + log.Error("could not parse slot", "Slot", headerRes.Data[0].Header.Message.Slot, "err", err) + return uint64(0), errors.New("invalid response") + } + return uint64(slot), nil +} + +func fetchEpochProposersMap(endpoint string, epoch uint64) (map[uint64]PubkeyHex, error) { + proposerDutiesResponse := &struct { + Data []struct { + PubkeyHex string `json:"pubkey"` + Slot string `json:"slot"` + } `json:"data"` + }{} + + err := fetchBeacon(fmt.Sprintf("%s/eth/v1/validator/duties/proposer/%d", endpoint, epoch), proposerDutiesResponse) + if err != nil { + return nil, err + } + + proposersMap := make(map[uint64]PubkeyHex) + for _, proposerDuty := range proposerDutiesResponse.Data { + slot, err := strconv.Atoi(proposerDuty.Slot) + if err != nil { + log.Error("could not parse slot", "Slot", proposerDuty.Slot, "err", err) + continue + } + proposersMap[uint64(slot)] = PubkeyHex(proposerDuty.PubkeyHex) + } + return proposersMap, nil +} + +func fetchBeacon(url string, dst any) error { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + log.Error("invalid request", "url", url, "err", err) + return err + } + req.Header.Set("accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Error("client refused", "url", url, "err", err) + return err + } + defer resp.Body.Close() + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + log.Error("could not read response body", "url", url, "err", err) + return err + } + + if resp.StatusCode >= 300 { + ec := &struct { + Code int `json:"code"` + Message string `json:"message"` + }{} + if err = json.Unmarshal(bodyBytes, ec); err != nil { + log.Error("Couldn't unmarshal error from beacon node", "url", url, "body", string(bodyBytes)) + return errors.New("could not unmarshal error response from beacon node") + } + return errors.New(ec.Message) + } + + err = json.Unmarshal(bodyBytes, dst) + if err != nil { + log.Error("could not unmarshal response", "url", url, "resp", string(bodyBytes), "dst", dst, "err", err) + return err + } + + log.Info("fetched", "url", url, "res", dst) + return nil +} diff --git a/builder/beacon_client_test.go b/builder/beacon_client_test.go new file mode 100644 index 0000000000..c4cb9d6814 --- /dev/null +++ b/builder/beacon_client_test.go @@ -0,0 +1,268 @@ +package builder + +import ( + "net/http" + "net/http/httptest" + "strconv" + "testing" + + "github.com/gorilla/mux" + "github.com/stretchr/testify/require" +) + +type mockBeaconNode struct { + srv *httptest.Server + + proposerDuties map[int][]byte + forkResp map[int][]byte + headersCode int + headersResp []byte +} + +func newMockBeaconNode() *mockBeaconNode { + r := mux.NewRouter() + srv := httptest.NewServer(r) + + mbn := &mockBeaconNode{ + srv: srv, + + proposerDuties: make(map[int][]byte), + forkResp: make(map[int][]byte), + headersCode: 200, + headersResp: []byte{}, + } + + r.HandleFunc("/eth/v1/validator/duties/proposer/{epoch}", func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + epochStr, ok := vars["epoch"] + if !ok { + http.Error(w, `{ "code": 400, "message": "Invalid epoch" }`, 400) + return + } + epoch, err := strconv.Atoi(epochStr) + if err != nil { + http.Error(w, `{ "code": 400, "message": "Invalid epoch" }`, 400) + return + } + + resp, found := mbn.proposerDuties[epoch] + if !found { + http.Error(w, `{ "code": 400, "message": "Invalid epoch" }`, 400) + return + } + + w.Header().Set("Content-Type", "application/json") + w.Write(resp) + }) + + r.HandleFunc("/eth/v1/beacon/headers", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(mbn.headersCode) + w.Write(mbn.headersResp) + }) + + return mbn +} + +func TestFetchBeacon(t *testing.T) { + mbn := newMockBeaconNode() + defer mbn.srv.Close() + + mbn.headersCode = 200 + mbn.headersResp = []byte(`{ "data": [ { "header": { "message": { "slot": "10", "proposer_index": "1" } } } ] }`) + + // Green path + headersResp := struct { + Data []struct { + Header struct { + Message struct { + Slot string `json:"slot"` + } `json:"message"` + } `json:"header"` + } `json:"data"` + }{} + err := fetchBeacon(mbn.srv.URL+"/eth/v1/beacon/headers", &headersResp) + require.NoError(t, err) + require.Equal(t, "10", headersResp.Data[0].Header.Message.Slot) + + // Wrong dst + wrongForkResp := struct { + Data []struct { + Slot string `json:"slot"` + } + }{} + err = fetchBeacon(mbn.srv.URL+"/eth/v1/beacon/headers", &wrongForkResp) + require.NoError(t, err) + require.Equal(t, wrongForkResp.Data[0].Slot, "") + + mbn.headersCode = 400 + mbn.headersResp = []byte(`{ "code": 400, "message": "Invalid call" }`) + err = fetchBeacon(mbn.srv.URL+"/eth/v1/beacon/headers", &headersResp) + require.EqualError(t, err, "Invalid call") +} + +func TestFetchCurrentSlot(t *testing.T) { + mbn := newMockBeaconNode() + defer mbn.srv.Close() + + mbn.headersResp = []byte(`{ + "execution_optimistic": false, + "data": [ + { + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "canonical": true, + "header": { + "message": { + "slot": "101", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } + ] +}`) + + slot, err := fetchCurrentSlot(mbn.srv.URL) + require.NoError(t, err) + require.Equal(t, uint64(101), slot) + + mbn.headersResp = []byte(`{ + "execution_optimistic": false, + "data": [ + { + "header": { + "message": { + "slot": "xxx" + } + } + } + ] +}`) + + slot, err = fetchCurrentSlot(mbn.srv.URL) + require.EqualError(t, err, "invalid response") + require.Equal(t, uint64(0), slot) +} + +func TestFetchEpochProposersMap(t *testing.T) { + mbn := newMockBeaconNode() + defer mbn.srv.Close() + + mbn.proposerDuties[10] = []byte(`{ + "dependent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "execution_optimistic": false, + "data": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "validator_index": "1", + "slot": "1" + }, + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b", + "validator_index": "2", + "slot": "2" + } + ] +}`) + + proposersMap, err := fetchEpochProposersMap(mbn.srv.URL, 10) + require.NoError(t, err) + require.Equal(t, 2, len(proposersMap)) + require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"), proposersMap[1]) + require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b"), proposersMap[2]) +} + +func TestOnForkchoiceUpdate(t *testing.T) { + mbn := newMockBeaconNode() + defer mbn.srv.Close() + + mbn.headersResp = []byte(`{ "data": [ { "header": { "message": { "slot": "31", "proposer_index": "1" } } } ] }`) + + mbn.proposerDuties[1] = []byte(`{ + "dependent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "execution_optimistic": false, + "data": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "validator_index": "1", + "slot": "31" + }, + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b", + "validator_index": "2", + "slot": "32" + }, + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74c", + "validator_index": "3", + "slot": "33" + } + ] +}`) + + bc := NewBeaconClient(mbn.srv.URL) + pubkeyHex, err := bc.onForkchoiceUpdate() + require.NoError(t, err) + require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b"), pubkeyHex) + + pubkeyHex, err = bc.getProposerForNextSlot(32) + require.NoError(t, err) + require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b"), pubkeyHex) + + pubkeyHex, err = bc.getProposerForNextSlot(31) + require.EqualError(t, err, "slot out of sync") + + pubkeyHex, err = bc.getProposerForNextSlot(33) + require.EqualError(t, err, "slot out of sync") + + mbn.headersCode = 404 + mbn.headersResp = []byte(`{ "code": 404, "message": "State not found" }`) + + pubkeyHex, err = NewBeaconClient(mbn.srv.URL).onForkchoiceUpdate() + require.EqualError(t, err, "State not found") + require.Equal(t, PubkeyHex(""), pubkeyHex) + + // Check that client does not fetch new proposers if epoch did not change + mbn.headersCode = 200 + mbn.headersResp = []byte(`{ "data": [ { "header": { "message": { "slot": "31", "proposer_index": "1" } } } ] }`) + mbn.proposerDuties[1] = []byte(`{ + "data": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74d", + "validator_index": "4", + "slot": "32" + } + ] +}`) + + pubkeyHex, err = bc.onForkchoiceUpdate() + require.NoError(t, err, "") + require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b"), pubkeyHex) + + mbn.headersResp = []byte(`{ "data": [ { "header": { "message": { "slot": "63", "proposer_index": "1" } } } ] }`) + mbn.proposerDuties[2] = []byte(`{ + "data": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74d", + "validator_index": "4", + "slot": "64" + } + ] +}`) + + pubkeyHex, err = bc.onForkchoiceUpdate() + require.NoError(t, err, "") + require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74d"), pubkeyHex) + + pubkeyHex, err = bc.getProposerForNextSlot(64) + require.NoError(t, err) + require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74d"), pubkeyHex) + + // Check proposers map error is routed out + mbn.headersResp = []byte(`{ "data": [ { "header": { "message": { "slot": "65", "proposer_index": "1" } } } ] }`) + pubkeyHex, err = bc.onForkchoiceUpdate() + require.EqualError(t, err, "inconsistent proposer mapping") +} diff --git a/builder/index.go b/builder/index.go new file mode 100644 index 0000000000..6e1e02e4db --- /dev/null +++ b/builder/index.go @@ -0,0 +1,90 @@ +package builder + +import ( + "html/template" +) + +func parseIndexTemplate() (*template.Template, error) { + return template.New("index").Parse(` + + + + + + + + Boost Block Builder + + + + + + + + + + + + +
+
+

+ +

+ Boost Block Builder +

+ +

+

+ +

+ +
+ +

+

+ Registered Validators: {{ .NoValidators }} +

+

+ +
+ +

+

+ Best Header +

+
{{ .Header }}
+

+ +
+ +

+

+ Best Payload +

+
{{ .Blocks }}
+

+ +
+
+ + + +`) +} diff --git a/builder/service.go b/builder/service.go new file mode 100644 index 0000000000..2b47787174 --- /dev/null +++ b/builder/service.go @@ -0,0 +1,108 @@ +package builder + +import ( + "errors" + "net/http" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/gorilla/mux" + + "github.com/flashbots/go-boost-utils/bls" + boostTypes "github.com/flashbots/go-boost-utils/types" + + "github.com/flashbots/go-utils/httplogger" +) + +const ( + _PathStatus = "/eth/v1/builder/status" + _PathRegisterValidator = "/eth/v1/builder/validators" + _PathGetHeader = "/eth/v1/builder/header/{slot:[0-9]+}/{parent_hash:0x[a-fA-F0-9]+}/{pubkey:0x[a-fA-F0-9]+}" + _PathGetPayload = "/eth/v1/builder/blinded_blocks" +) + +type Service struct { + srv *http.Server +} + +func (s *Service) Start() { + log.Info("Service started") + go s.srv.ListenAndServe() +} + +func getRouter(backend *Backend) http.Handler { + router := mux.NewRouter() + + // Add routes + router.HandleFunc("/", backend.handleIndex).Methods(http.MethodGet) + router.HandleFunc(_PathStatus, backend.handleStatus).Methods(http.MethodGet) + router.HandleFunc(_PathRegisterValidator, backend.handleRegisterValidator).Methods(http.MethodPost) + router.HandleFunc(_PathGetHeader, backend.handleGetHeader).Methods(http.MethodGet) + router.HandleFunc(_PathGetPayload, backend.handleGetPayload).Methods(http.MethodPost) + + // Add logging and return router + loggedRouter := httplogger.LoggingMiddleware(router) + return loggedRouter +} + +func NewService(listenAddr string, backend *Backend) *Service { + return &Service{ + srv: &http.Server{ + Addr: listenAddr, + Handler: getRouter(backend), + /* + ReadTimeout: + ReadHeaderTimeout: + WriteTimeout: + IdleTimeout: + */ + }, + } +} + +type BuilderConfig struct { + EnableValidatorChecks bool + SecretKey string + ListenAddr string + GenesisForkVersion string + BellatrixForkVersion string + GenesisValidatorsRoot string + BeaconEndpoint string +} + +func Register(stack *node.Node, backend *eth.Ethereum, cfg *BuilderConfig) error { + envSkBytes, err := hexutil.Decode(cfg.SecretKey) + if err != nil { + return errors.New("incorrect builder API secret key provided") + } + + sk, err := bls.SecretKeyFromBytes(envSkBytes[:]) + if err != nil { + return errors.New("incorrect builder API secret key provided") + } + + genesisForkVersionBytes, err := hexutil.Decode(cfg.GenesisForkVersion) + var genesisForkVersion [4]byte + copy(genesisForkVersion[:], genesisForkVersionBytes[:4]) + builderSigningDomain := boostTypes.ComputeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersion, boostTypes.Root{}) + + genesisValidatorsRoot := boostTypes.Root(common.HexToHash(cfg.GenesisValidatorsRoot)) + bellatrixForkVersionBytes, err := hexutil.Decode(cfg.BellatrixForkVersion) + var bellatrixForkVersion [4]byte + copy(bellatrixForkVersion[:], bellatrixForkVersionBytes[:4]) + proposerSigningDomain := boostTypes.ComputeDomain(boostTypes.DomainTypeBeaconProposer, bellatrixForkVersion, genesisValidatorsRoot) + + var beaconClient IBeaconClient + beaconClient = NewBeaconClient(cfg.BeaconEndpoint) + + builderBackend := NewBackend(sk, beaconClient, builderSigningDomain, proposerSigningDomain, cfg.EnableValidatorChecks) + builderService := NewService(cfg.ListenAddr, builderBackend) + builderService.Start() + + backend.SetSealedBlockHook(builderBackend.newSealedBlock) + backend.SetForkchoiceHook(builderBackend.onForkchoice) + return nil +} diff --git a/builder/validator.go b/builder/validator.go new file mode 100644 index 0000000000..b1554a4f95 --- /dev/null +++ b/builder/validator.go @@ -0,0 +1,49 @@ +package builder + +import ( + "time" + + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/flashbots/go-boost-utils/bls" + boostTypes "github.com/flashbots/go-boost-utils/types" +) + +type ValidatorPrivateData struct { + sk *bls.SecretKey + Pk hexutil.Bytes +} + +func NewRandomValidator() *ValidatorPrivateData { + sk, pk, err := bls.GenerateNewKeypair() + if err != nil { + return nil + } + return &ValidatorPrivateData{sk, pk.Compress()} +} + +func (v *ValidatorPrivateData) Sign(msg boostTypes.HashTreeRoot, d boostTypes.Domain) (boostTypes.Signature, error) { + return boostTypes.SignMessage(msg, d, v.sk) +} + +func (v *ValidatorPrivateData) PrepareRegistrationMessage(feeRecipientHex string) (boostTypes.SignedValidatorRegistration, error) { + address, err := boostTypes.HexToAddress(feeRecipientHex) + if err != nil { + return boostTypes.SignedValidatorRegistration{}, err + } + + pubkey := boostTypes.PublicKey{} + pubkey.FromSlice(v.Pk) + + msg := &boostTypes.RegisterValidatorRequestMessage{ + FeeRecipient: address, + GasLimit: 1000, + Timestamp: uint64(time.Now().UnixMilli()), + Pubkey: pubkey, + } + signature, err := v.Sign(msg, boostTypes.DomainBuilder) + if err != nil { + return boostTypes.SignedValidatorRegistration{}, err + } + return boostTypes.SignedValidatorRegistration{msg, signature}, nil +} diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 30565fda61..1fe5e8ed27 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/accounts/usbwallet" + builder "github.com/ethereum/go-ethereum/builder" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/eth/ethconfig" @@ -159,12 +160,23 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { if ctx.IsSet(utils.OverrideTerminalTotalDifficulty.Name) { cfg.Eth.OverrideTerminalTotalDifficulty = flags.GlobalBig(ctx, utils.OverrideTerminalTotalDifficulty.Name) } + if ctx.IsSet(utils.OverrideTerminalTotalDifficultyPassed.Name) { override := ctx.Bool(utils.OverrideTerminalTotalDifficultyPassed.Name) cfg.Eth.OverrideTerminalTotalDifficultyPassed = &override } - backend, eth := utils.RegisterEthService(stack, &cfg.Eth) + bpConfig := &builder.BuilderConfig{ + EnableValidatorChecks: ctx.IsSet(utils.BuilderEnableValidatorChecks.Name), + SecretKey: ctx.String(utils.BuilderSecretKey.Name), + ListenAddr: ctx.String(utils.BuilderListenAddr.Name), + GenesisForkVersion: ctx.String(utils.BuilderGenesisForkVersion.Name), + BellatrixForkVersion: ctx.String(utils.BuilderBellatrixForkVersion.Name), + GenesisValidatorsRoot: ctx.String(utils.BuilderGenesisValidatorsRoot.Name), + BeaconEndpoint: ctx.String(utils.BuilderBeaconEndpoint.Name), + } + + backend, eth := utils.RegisterEthService(stack, &cfg.Eth, bpConfig) // Warn users to migrate if they have a legacy freezer format. if eth != nil && !ctx.IsSet(utils.IgnoreLegacyReceiptsFlag.Name) { diff --git a/cmd/geth/main.go b/cmd/geth/main.go index b9e3ed31e8..ab159b91de 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -157,6 +157,16 @@ var ( configFileFlag, }, utils.NetworkFlags, utils.DatabasePathFlags) + builderApiFlags = []cli.Flag{ + utils.BuilderEnableValidatorChecks, + utils.BuilderSecretKey, + utils.BuilderListenAddr, + utils.BuilderGenesisForkVersion, + utils.BuilderBellatrixForkVersion, + utils.BuilderGenesisValidatorsRoot, + utils.BuilderBeaconEndpoint, + } + rpcFlags = []cli.Flag{ utils.HTTPEnabledFlag, utils.HTTPListenAddrFlag, @@ -247,6 +257,7 @@ func init() { app.Flags = flags.Merge( nodeFlags, rpcFlags, + builderApiFlags, consoleFlags, debug.Flags, metricsFlags, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 9e95193343..c76e2f37ee 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" + builder "github.com/ethereum/go-ethereum/builder" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/consensus" @@ -660,7 +661,47 @@ var ( Usage: "Geth will start up even if there are legacy receipts in freezer", Category: flags.MiscCategory, } - + // Builder API settings + BuilderEnableValidatorChecks = &cli.BoolFlag{ + Name: "builder.validator_checks", + Usage: "Enable the validator checks", + } + BuilderSecretKey = &cli.StringFlag{ + Name: "builder.secret_key", + Usage: "Builder API key used for signing headers", + EnvVars: []string{"BUILDER_SECRET_KEY"}, + Value: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11", + } + BuilderListenAddr = &cli.StringFlag{ + Name: "builder.listen_addr", + Usage: "Listening address for builder endpoint", + EnvVars: []string{"BUILDER_LISTEN_ADDR"}, + Value: ":28545", + } + BuilderGenesisForkVersion = &cli.StringFlag{ + Name: "builder.genesis_fork_version", + Usage: "Gensis fork version. For kiln use 0x70000069", + EnvVars: []string{"BUILDER_GENESIS_FORK_VERSION"}, + Value: "0x00000000", + } + BuilderBellatrixForkVersion = &cli.StringFlag{ + Name: "builder.bellatrix_fork_version", + Usage: "Bellatrix fork version. For kiln use 0x70000071", + EnvVars: []string{"BUILDER_BELLATRIX_FORK_VERSION"}, + Value: "0x02000000", + } + BuilderGenesisValidatorsRoot = &cli.StringFlag{ + Name: "builder.genesis_validators_root", + Usage: "Genesis validators root of the network. For kiln use 0x99b09fcd43e5905236c370f184056bec6e6638cfc31a323b304fc4aa789cb4ad", + EnvVars: []string{"BUILDER_GENESIS_VALIDATORS_ROOT"}, + Value: "0x0000000000000000000000000000000000000000000000000000000000000000", + } + BuilderBeaconEndpoint = &cli.StringFlag{ + Name: "builder.beacon_endpoint", + Usage: "Beacon endpoint to connect to for beacon chain data", + EnvVars: []string{"BUILDER_BEACON_ENDPOINT"}, + Value: "http://127.0.0.1:5052", + } // RPC settings IPCDisabledFlag = &cli.BoolFlag{ Name: "ipcdisable", @@ -1987,7 +2028,7 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) { // RegisterEthService adds an Ethereum client to the stack. // The second return value is the full node instance, which may be nil if the // node is running as a light client. -func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) { +func RegisterEthService(stack *node.Node, cfg *ethconfig.Config, bpCfg *builder.BuilderConfig) (ethapi.Backend, *eth.Ethereum) { if cfg.SyncMode == downloader.LightSync { backend, err := les.New(stack, cfg) if err != nil { @@ -2012,6 +2053,11 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend if err := ethcatalyst.Register(stack, backend); err != nil { Fatalf("Failed to register the Engine API service: %v", err) } + + if err := builder.Register(stack, backend, bpCfg); err != nil { + Fatalf("Failed to register the builder service: %v", err) + } + stack.RegisterAPIs(tracers.APIs(backend.APIBackend)) return backend.APIBackend, backend } diff --git a/core/beacon/types.go b/core/beacon/types.go index e25d724c0d..d0e878bde1 100644 --- a/core/beacon/types.go +++ b/core/beacon/types.go @@ -33,6 +33,7 @@ type PayloadAttributesV1 struct { Timestamp uint64 `json:"timestamp" gencodec:"required"` Random common.Hash `json:"prevRandao" gencodec:"required"` SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` + GasLimit uint64 } // JSON type overrides for PayloadAttributesV1. diff --git a/core/types/block.go b/core/types/block.go index 7525a88f5a..c5076f1142 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -168,6 +168,8 @@ type Block struct { uncles []*Header transactions Transactions + Profit *big.Int + // caches hash atomic.Value size atomic.Value diff --git a/eth/backend.go b/eth/backend.go index 7782076363..7da37eb5a1 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/core" + beaconTypes "github.com/ethereum/go-ethereum/core/beacon" "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/pruner" @@ -85,6 +86,9 @@ type Ethereum struct { bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports closeBloomHandler chan struct{} + newSealedBlockHook func(*beaconTypes.ExecutableDataV1, *types.Block) + forkchoiceHook func(*beaconTypes.PayloadAttributesV1) + APIBackend *EthAPIBackend miner *miner.Miner @@ -353,6 +357,27 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) { return common.Address{}, fmt.Errorf("etherbase must be explicitly specified") } +func (s *Ethereum) SetSealedBlockHook(newSealedBlockHook func(*beaconTypes.ExecutableDataV1, *types.Block)) { + s.newSealedBlockHook = newSealedBlockHook +} + +func (s *Ethereum) NewSealedBlock(data *beaconTypes.ExecutableDataV1, block *types.Block) { + if s.newSealedBlockHook != nil { + s.newSealedBlockHook(data, block) + } +} + +func (s *Ethereum) SetForkchoiceHook(forkchoiceHook func(*beaconTypes.PayloadAttributesV1)) { + s.forkchoiceHook = forkchoiceHook +} + +func (s *Ethereum) ForkchoiceHook(payloadAttributes *beaconTypes.PayloadAttributesV1) { + // Possibly modifies payloadAttributes's fee recipient + if s.forkchoiceHook != nil { + s.forkchoiceHook(payloadAttributes) + } +} + // isLocalBlock checks whether the specified block is mined // by local miner accounts. // diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index b159f34e64..cf748c5545 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -155,7 +155,11 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update beacon.ForkchoiceStateV1, pa api.forkchoiceLock.Lock() defer api.forkchoiceLock.Unlock() - log.Trace("Engine API request received", "method", "ForkchoiceUpdated", "head", update.HeadBlockHash, "finalized", update.FinalizedBlockHash, "safe", update.SafeBlockHash) + log.Info("Engine API request received", "method", "ForkchoiceUpdated", "head", update.HeadBlockHash, "finalized", update.FinalizedBlockHash, "safe", update.SafeBlockHash) + + // Adjusts payload attributes to next slot's validator preferences + api.eth.ForkchoiceHook(payloadAttributes) + if update.HeadBlockHash == (common.Hash{}) { log.Warn("Forkchoice requested update to zero hash") return beacon.STATUS_INVALID, nil // TODO(karalabe): Why does someone send us this? @@ -277,20 +281,24 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update beacon.ForkchoiceStateV1, pa // might replace it arbitrarily many times in between. if payloadAttributes != nil { // Create an empty block first which can be used as a fallback - empty, err := api.eth.Miner().GetSealingBlockSync(update.HeadBlockHash, payloadAttributes.Timestamp, payloadAttributes.SuggestedFeeRecipient, payloadAttributes.Random, true) + empty, err := api.eth.Miner().GetSealingBlockSync(update.HeadBlockHash, payloadAttributes.Timestamp, payloadAttributes.SuggestedFeeRecipient, payloadAttributes.GasLimit, payloadAttributes.Random, true) if err != nil { log.Error("Failed to create empty sealing payload", "err", err) return valid(nil), beacon.InvalidPayloadAttributes.With(err) } // Send a request to generate a full block in the background. // The result can be obtained via the returned channel. - resCh, err := api.eth.Miner().GetSealingBlockAsync(update.HeadBlockHash, payloadAttributes.Timestamp, payloadAttributes.SuggestedFeeRecipient, payloadAttributes.Random, false) + resCh, err := api.eth.Miner().GetSealingBlockAsync(update.HeadBlockHash, payloadAttributes.Timestamp, payloadAttributes.SuggestedFeeRecipient, payloadAttributes.GasLimit, payloadAttributes.Random, false) if err != nil { log.Error("Failed to create async sealing payload", "err", err) return valid(nil), beacon.InvalidPayloadAttributes.With(err) } id := computePayloadId(update.HeadBlockHash, payloadAttributes) - api.localBlocks.put(id, &payload{empty: empty, result: resCh}) + resultPayload := &payload{empty: empty, result: resCh} + api.localBlocks.put(id, resultPayload) + go func() { + api.eth.NewSealedBlock(resultPayload.resolve()) + }() return valid(&id), nil } return valid(nil), nil diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index 0d945993eb..68fc0a05ff 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -603,7 +603,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { } func assembleBlock(api *ConsensusAPI, parentHash common.Hash, params *beacon.PayloadAttributesV1) (*beacon.ExecutableDataV1, error) { - block, err := api.eth.Miner().GetSealingBlockSync(parentHash, params.Timestamp, params.SuggestedFeeRecipient, params.Random, false) + block, err := api.eth.Miner().GetSealingBlockSync(parentHash, params.Timestamp, params.SuggestedFeeRecipient, 0, params.Random, false) if err != nil { return nil, err } @@ -846,7 +846,7 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) { Random: crypto.Keccak256Hash([]byte{byte(1)}), SuggestedFeeRecipient: parent.Coinbase(), } - empty, err := api.eth.Miner().GetSealingBlockSync(parent.Hash(), params.Timestamp, params.SuggestedFeeRecipient, params.Random, true) + empty, err := api.eth.Miner().GetSealingBlockSync(parent.Hash(), params.Timestamp, params.SuggestedFeeRecipient, 0, params.Random, true) if err != nil { t.Fatalf("error preparing payload, err=%v", err) } diff --git a/eth/catalyst/queue.go b/eth/catalyst/queue.go index ff8edc1201..2995ff4860 100644 --- a/eth/catalyst/queue.go +++ b/eth/catalyst/queue.go @@ -47,7 +47,7 @@ type payload struct { // resolve extracts the generated full block from the given channel if possible // or fallback to empty block as an alternative. -func (req *payload) resolve() *beacon.ExecutableDataV1 { +func (req *payload) resolve() (*beacon.ExecutableDataV1, *types.Block) { // this function can be called concurrently, prevent any // concurrency issue in the first place. req.lock.Lock() @@ -71,9 +71,9 @@ func (req *payload) resolve() *beacon.ExecutableDataV1 { } if req.block != nil { - return beacon.BlockToExecutableData(req.block) + return beacon.BlockToExecutableData(req.block), req.block } - return beacon.BlockToExecutableData(req.empty) + return beacon.BlockToExecutableData(req.empty), req.empty } // payloadQueueItem represents an id->payload tuple to store until it's retrieved @@ -120,7 +120,8 @@ func (q *payloadQueue) get(id beacon.PayloadID) *beacon.ExecutableDataV1 { return nil // no more items } if item.id == id { - return item.data.resolve() + data, _ := item.data.resolve() + return data } } return nil diff --git a/go.mod b/go.mod index 4a769c7a2d..e14925890f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum/go-ethereum -go 1.17 +go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 @@ -9,8 +9,8 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.1.1 github.com/aws/aws-sdk-go-v2/credentials v1.1.1 github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 - github.com/btcsuite/btcd/btcec/v2 v2.2.0 - github.com/cespare/cp v0.1.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.3 + github.com/cespare/cp v1.1.1 github.com/cloudflare/cloudflare-go v0.14.0 github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f github.com/davecgh/go-spew v1.1.1 @@ -18,35 +18,38 @@ require ( github.com/docker/docker v1.6.2 github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf github.com/edsrzf/mmap-go v1.0.0 - github.com/fatih/color v1.7.0 + github.com/fatih/color v1.9.0 github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff + github.com/flashbots/go-boost-utils v0.1.2 + github.com/flashbots/go-utils v0.4.4 + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 github.com/go-stack/stack v1.8.0 github.com/golang-jwt/jwt/v4 v4.3.0 github.com/golang/protobuf v1.5.2 github.com/golang/snappy v0.0.4 - github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa - github.com/google/uuid v1.2.0 - github.com/gorilla/websocket v1.4.2 + github.com/google/gofuzz v1.2.0 + github.com/google/uuid v1.3.0 + github.com/gorilla/mux v1.8.0 + github.com/gorilla/websocket v1.5.0 github.com/graph-gophers/graphql-go v1.3.0 github.com/hashicorp/go-bexpr v0.1.10 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/bloomfilter/v2 v2.0.3 github.com/holiman/uint256 v1.2.0 - github.com/huin/goupnp v1.0.3 + github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204 github.com/influxdata/influxdb v1.8.3 github.com/influxdata/influxdb-client-go/v2 v2.4.0 github.com/jackpal/go-nat-pmp v1.0.2 github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e - github.com/julienschmidt/httprouter v1.2.0 + github.com/julienschmidt/httprouter v1.3.0 github.com/karalabe/usb v0.0.2 - github.com/mattn/go-colorable v0.1.8 - github.com/mattn/go-isatty v0.0.12 + github.com/mattn/go-colorable v0.1.9 + github.com/mattn/go-isatty v0.0.14 github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 - github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 - github.com/prometheus/tsdb v0.7.1 + github.com/peterh/liner v1.2.0 + github.com/prometheus/tsdb v0.10.0 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible @@ -56,50 +59,54 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef github.com/urfave/cli/v2 v2.10.2 - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 + golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba - golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 + golang.org/x/tools v0.1.10 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce + gopkg.in/urfave/cli.v1 v1.20.0 ) require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect + github.com/allegro/bigcache v1.2.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect github.com/aws/smithy-go v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/deepmap/oapi-codegen v1.8.2 // indirect github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect + github.com/ferranbt/fastssz v0.1.1-0.20220303160658-88bb965b6747 // indirect github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect - github.com/go-logfmt/logfmt v0.4.0 // indirect github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect - github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect + github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/naoina/go-stringutil v0.1.0 // indirect - github.com/opentracing/opentracing-go v1.1.0 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect google.golang.org/protobuf v1.26.0 // indirect diff --git a/go.sum b/go.sum index 4b27867fbc..0cdb466eed 100644 --- a/go.sum +++ b/go.sum @@ -25,19 +25,20 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSu github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY= +github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/aws/aws-sdk-go-v2 v1.2.0 h1:BS+UYpbsElC82gB+2E2jiCBg36i8HlubTB/dO/moQ9c= @@ -62,18 +63,29 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= -github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -89,6 +101,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -98,6 +111,7 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= @@ -119,21 +133,26 @@ github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/ferranbt/fastssz v0.1.1-0.20220303160658-88bb965b6747 h1:0w9ZW2gY6Ws640PkDsyB1CK1ndAPJJ0mJbsDojQFl5c= +github.com/ferranbt/fastssz v0.1.1-0.20220303160658-88bb965b6747/go.mod h1:S8yiDeAXy8f88W4Ul+0dBMPx49S05byYbmZD6Uv94K4= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq6Q+cGWcGHz0FjGR3QqcInWcW0= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/flashbots/go-boost-utils v0.1.2 h1:xcwO6rhLmdbZ+ttN8PjHQynqY1pm+RCA56eGP9wPp10= +github.com/flashbots/go-boost-utils v0.1.2/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= +github.com/flashbots/go-utils v0.4.4 h1:J0LUifVEpVYE+ZbK/DeGay4E3B6+Yh8pKLgfv5A0Oq0= +github.com/flashbots/go-utils v0.4.4/go.mod h1:weSbiNnH+xsmK8t3TDDJxluv4+qnwRWmKay2QQa8Yfc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc= github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -156,7 +175,6 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5Nq github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -183,6 +201,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -198,22 +217,22 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= @@ -227,11 +246,10 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204 h1:+EYBkW+dbi3F/atB+LSQZSWh7+HNrV3A/N0y6DSoy9k= +github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vAiBg8= @@ -251,36 +269,43 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= @@ -293,20 +318,28 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -320,37 +353,30 @@ github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hz github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg= +github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -365,17 +391,17 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -408,14 +434,8 @@ github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8 github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 h1:m+8fKfQwCAy1QjzINvKe/pYtLjo2dl59x2w9YSEJxuY= github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= -github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= -github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= @@ -434,25 +454,27 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= +golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -463,7 +485,6 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -483,9 +504,9 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4= -golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -509,11 +530,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -533,7 +551,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -560,17 +577,13 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -614,14 +627,12 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 h1:0c3L82FDQ5rt1bjTBlchS8t6RQ6299/+5bWMnRLh+uI= -golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -685,6 +696,8 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/miner/miner.go b/miner/miner.go index 1e9607a76a..a51f49e82a 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -245,8 +245,8 @@ func (miner *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscript // there is always a result that will be returned through the result channel. // The difference is that if the execution fails, the returned result is nil // and the concrete error is dropped silently. -func (miner *Miner) GetSealingBlockAsync(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, noTxs bool) (chan *types.Block, error) { - resCh, _, err := miner.worker.getSealingBlock(parent, timestamp, coinbase, random, noTxs) +func (miner *Miner) GetSealingBlockAsync(parent common.Hash, timestamp uint64, coinbase common.Address, gasLimit uint64, random common.Hash, noTxs bool) (chan *types.Block, error) { + resCh, _, err := miner.worker.getSealingBlock(parent, timestamp, coinbase, gasLimit, random, noTxs) if err != nil { return nil, err } @@ -256,8 +256,8 @@ func (miner *Miner) GetSealingBlockAsync(parent common.Hash, timestamp uint64, c // GetSealingBlockSync creates a sealing block according to the given parameters. // If the generation is failed or the underlying work is already closed, an error // will be returned. -func (miner *Miner) GetSealingBlockSync(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, noTxs bool) (*types.Block, error) { - resCh, errCh, err := miner.worker.getSealingBlock(parent, timestamp, coinbase, random, noTxs) +func (miner *Miner) GetSealingBlockSync(parent common.Hash, timestamp uint64, coinbase common.Address, gasLimit uint64, random common.Hash, noTxs bool) (*types.Block, error) { + resCh, errCh, err := miner.worker.getSealingBlock(parent, timestamp, coinbase, gasLimit, random, noTxs) if err != nil { return nil, err } diff --git a/miner/stress/beacon/main.go b/miner/stress/beacon/main.go index 88af84c7fc..b30365052d 100644 --- a/miner/stress/beacon/main.go +++ b/miner/stress/beacon/main.go @@ -141,9 +141,9 @@ func newNode(typ nodetype, genesis *core.Genesis, enodes []*enode.Node) *ethNode } } -func (n *ethNode) assembleBlock(parentHash common.Hash, parentTimestamp uint64) (*beacon.ExecutableDataV1, error) { +func (n *ethNode) assembleBlock(parentHash common.Hash, parentTimestamp uint64) (*beacon.ExecutableDataV1, *types.Block, error) { if n.typ != eth2MiningNode { - return nil, errors.New("invalid node type") + return nil, nil, errors.New("invalid node type") } timestamp := uint64(time.Now().Unix()) if timestamp <= parentTimestamp { @@ -161,9 +161,10 @@ func (n *ethNode) assembleBlock(parentHash common.Hash, parentTimestamp uint64) } payload, err := n.api.ForkchoiceUpdatedV1(fcState, &payloadAttribute) if err != nil { - return nil, err + return nil, nil, err } - return n.api.GetPayloadV1(*payload.PayloadID) + data, err := n.api.GetPayloadV1(*payload.PayloadID) + return data, nil, nil } func (n *ethNode) insertBlock(eb beacon.ExecutableDataV1) error { @@ -358,7 +359,7 @@ func (mgr *nodeManager) run() { if parentBlock.NumberU64() == 0 { timestamp = uint64(time.Now().Unix()) - uint64(blockIntervalInt) } - ed, err := producers[0].assembleBlock(hash, timestamp) + ed, _, err := producers[0].assembleBlock(hash, timestamp) if err != nil { log.Error("Failed to assemble the block", "err", err) continue diff --git a/miner/worker.go b/miner/worker.go index 93fb6288bb..be9e87fcb8 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -956,6 +956,7 @@ type generateParams struct { forceTime bool // Flag whether the given timestamp is immutable or not parentHash common.Hash // Parent block hash, empty means the latest chain head coinbase common.Address // The fee recipient address for including transaction + gasLimit uint64 // The validator's requested gas limit target random common.Hash // The randomness generated by beacon chain, empty before the merge noUncle bool // Flag whether the uncle block inclusion is allowed noExtra bool // Flag whether the extra field assignment is allowed @@ -987,11 +988,15 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { timestamp = parent.Time() + 1 } // Construct the sealing block header, set the extra field if it's allowed + gasTarget := genParams.gasLimit + if gasTarget == 0 { + gasTarget = w.config.GasCeil + } num := parent.Number() header := &types.Header{ ParentHash: parent.Hash(), Number: num.Add(num, common.Big1), - GasLimit: core.CalcGasLimit(parent.GasLimit(), w.config.GasCeil), + GasLimit: core.CalcGasLimit(parent.GasLimit(), gasTarget), Time: timestamp, Coinbase: genParams.coinbase, } @@ -1081,10 +1086,19 @@ func (w *worker) generateWork(params *generateParams) (*types.Block, error) { } defer work.discard() + coinbaseBalanceBefore := work.state.GetBalance(params.coinbase) + if !params.noTxs { w.fillTransactions(nil, work) } - return w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, work.unclelist(), work.receipts) + block, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, work.unclelist(), work.receipts) + if err != nil { + return nil, err + } + + coinbaseBalanceAfter := work.state.GetBalance(params.coinbase) + block.Profit = big.NewInt(0).Sub(coinbaseBalanceAfter, coinbaseBalanceBefore) + return block, nil } // commitWork generates several new sealing tasks based on the parent block @@ -1170,7 +1184,7 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti // getSealingBlock generates the sealing block based on the given parameters. // The generation result will be passed back via the given channel no matter // the generation itself succeeds or not. -func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, noTxs bool) (chan *types.Block, chan error, error) { +func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase common.Address, gasLimit uint64, random common.Hash, noTxs bool) (chan *types.Block, chan error, error) { var ( resCh = make(chan *types.Block, 1) errCh = make(chan error, 1) @@ -1181,6 +1195,7 @@ func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase forceTime: true, parentHash: parent, coinbase: coinbase, + gasLimit: gasLimit, random: random, noUncle: true, noExtra: true, diff --git a/miner/worker_test.go b/miner/worker_test.go index ec5ba67e1c..2b5af2ffc2 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -637,7 +637,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co // This API should work even when the automatic sealing is not enabled for _, c := range cases { - resChan, errChan, _ := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, false) + resChan, errChan, _ := w.getSealingBlock(c.parent, timestamp, c.coinbase, 0, c.random, false) block := <-resChan err := <-errChan if c.expectErr { @@ -655,7 +655,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co // This API should work even when the automatic sealing is enabled w.start() for _, c := range cases { - resChan, errChan, _ := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, false) + resChan, errChan, _ := w.getSealingBlock(c.parent, timestamp, c.coinbase, 0, c.random, false) block := <-resChan err := <-errChan if c.expectErr { From 3c0d5f1881de1504eac9249e7dcdc26988ba91a9 Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Thu, 2 Jun 2022 10:48:31 +0200 Subject: [PATCH 02/83] Adjust transactions root computation (#3) --- builder/backend.go | 26 +++++++------------------- builder/backend_test.go | 2 +- go.mod | 2 +- go.sum | 2 ++ 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/builder/backend.go b/builder/backend.go index 5473e280dc..acbc0640dd 100644 --- a/builder/backend.go +++ b/builder/backend.go @@ -3,7 +3,6 @@ package builder import ( "bytes" "encoding/json" - "fmt" "html/template" "math/big" "net/http" @@ -17,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/core/beacon" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/trie" "github.com/gorilla/mux" "github.com/flashbots/go-boost-utils/bls" @@ -358,7 +356,7 @@ func (b *Backend) newSealedBlock(data *beacon.ExecutableDataV1, block *types.Blo log.Info("newSealedBlock", "data", string(dataJson)) } payload := executableDataToExecutionPayload(data) - payloadHeader, err := payloadToPayloadHeader(payload) + payloadHeader, err := payloadToPayloadHeader(payload, data) if err != nil { log.Error("could not convert payload to header", "err", err) return @@ -371,23 +369,13 @@ func (b *Backend) newSealedBlock(data *beacon.ExecutableDataV1, block *types.Blo b.bestDataLock.Unlock() } -func decodeTransactions(enc []hexutil.Bytes) ([]*types.Transaction, error) { - var txs = make([]*types.Transaction, len(enc)) - for i, encTx := range enc { - var tx types.Transaction - if err := tx.UnmarshalBinary(encTx); err != nil { - return nil, fmt.Errorf("invalid transaction %d: %v", i, err) - } - txs[i] = &tx - } - return txs, nil -} - -func payloadToPayloadHeader(p *boostTypes.ExecutionPayload) (*boostTypes.ExecutionPayloadHeader, error) { - txs, err := decodeTransactions(p.Transactions) +func payloadToPayloadHeader(p *boostTypes.ExecutionPayload, data *beacon.ExecutableDataV1) (*boostTypes.ExecutionPayloadHeader, error) { + txs := boostTypes.Transactions{data.Transactions} + txroot, err := txs.HashTreeRoot() if err != nil { return nil, err } + return &boostTypes.ExecutionPayloadHeader{ ParentHash: p.ParentHash, FeeRecipient: p.FeeRecipient, @@ -399,10 +387,10 @@ func payloadToPayloadHeader(p *boostTypes.ExecutionPayload) (*boostTypes.Executi GasLimit: p.GasLimit, GasUsed: p.GasUsed, Timestamp: p.Timestamp, - ExtraData: []byte(p.ExtraData), + ExtraData: data.ExtraData, BaseFeePerGas: p.BaseFeePerGas, BlockHash: p.BlockHash, - TransactionsRoot: [32]byte(types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil))), + TransactionsRoot: [32]byte(txroot), }, nil } diff --git a/builder/backend_test.go b/builder/backend_test.go index dbd56d7c35..4b1e39a7e7 100644 --- a/builder/backend_test.go +++ b/builder/backend_test.go @@ -146,7 +146,7 @@ func TestGetHeader(t *testing.T) { err := json.Unmarshal(rr.Body.Bytes(), bid) require.NoError(t, err) - expectedHeader, err := payloadToPayloadHeader(executableDataToExecutionPayload(forkchoiceData)) + expectedHeader, err := payloadToPayloadHeader(executableDataToExecutionPayload(forkchoiceData), forkchoiceData) require.NoError(t, err) require.EqualValues(t, &boostTypes.BuilderBid{ Header: expectedHeader, diff --git a/go.mod b/go.mod index e14925890f..c9facd7947 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/fatih/color v1.9.0 github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 - github.com/flashbots/go-boost-utils v0.1.2 + github.com/flashbots/go-boost-utils v0.1.3-0.20220601173756-01db408b8c89 github.com/flashbots/go-utils v0.4.4 github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 github.com/go-stack/stack v1.8.0 diff --git a/go.sum b/go.sum index 0cdb466eed..4b979baa2d 100644 --- a/go.sum +++ b/go.sum @@ -143,6 +143,8 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlK github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flashbots/go-boost-utils v0.1.2 h1:xcwO6rhLmdbZ+ttN8PjHQynqY1pm+RCA56eGP9wPp10= github.com/flashbots/go-boost-utils v0.1.2/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= +github.com/flashbots/go-boost-utils v0.1.3-0.20220601173756-01db408b8c89 h1:3wVzFGJbXm8BjuFav3ZPKFAz01IY6JDjV38b3Ccuk2I= +github.com/flashbots/go-boost-utils v0.1.3-0.20220601173756-01db408b8c89/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= github.com/flashbots/go-utils v0.4.4 h1:J0LUifVEpVYE+ZbK/DeGay4E3B6+Yh8pKLgfv5A0Oq0= github.com/flashbots/go-utils v0.4.4/go.mod h1:weSbiNnH+xsmK8t3TDDJxluv4+qnwRWmKay2QQa8Yfc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= From 0211eab24ea59408e2edd4ce044e25744a027ccc Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Thu, 2 Jun 2022 11:36:53 +0200 Subject: [PATCH 03/83] Adjust logsBloom encoding (#4) --- builder/backend.go | 5 ++--- builder/backend_test.go | 1 + go.mod | 2 +- go.sum | 6 ++---- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/builder/backend.go b/builder/backend.go index acbc0640dd..7597666d57 100644 --- a/builder/backend.go +++ b/builder/backend.go @@ -399,14 +399,13 @@ func executableDataToExecutionPayload(data *beacon.ExecutableDataV1) *boostTypes for i, tx := range data.Transactions { transactionData[i] = hexutil.Bytes(tx) } - logsBloom := boostTypes.Bloom{} - logsBloom.FromSlice(data.LogsBloom) + return &boostTypes.ExecutionPayload{ ParentHash: [32]byte(data.ParentHash), FeeRecipient: [20]byte(data.FeeRecipient), StateRoot: [32]byte(data.StateRoot), ReceiptsRoot: [32]byte(data.ReceiptsRoot), - LogsBloom: logsBloom, + LogsBloom: boostTypes.Bloom(types.BytesToBloom(data.LogsBloom)), Random: [32]byte(data.Random), BlockNumber: data.Number, GasLimit: data.GasLimit, diff --git a/builder/backend_test.go b/builder/backend_test.go index 4b1e39a7e7..1158d06f25 100644 --- a/builder/backend_test.go +++ b/builder/backend_test.go @@ -118,6 +118,7 @@ func TestGetHeader(t *testing.T) { BlockHash: common.HexToHash("0xbfbfbfb"), BaseFeePerGas: big.NewInt(12), ExtraData: []byte{}, + LogsBloom: []byte{0x00, 0x05, 0x10}, } forkchoiceBlock := &types.Block{ Profit: big.NewInt(10), diff --git a/go.mod b/go.mod index c9facd7947..99146f88a4 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/fatih/color v1.9.0 github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 - github.com/flashbots/go-boost-utils v0.1.3-0.20220601173756-01db408b8c89 + github.com/flashbots/go-boost-utils v0.1.3-0.20220601182529-417a64679a5d github.com/flashbots/go-utils v0.4.4 github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 github.com/go-stack/stack v1.8.0 diff --git a/go.sum b/go.sum index 4b979baa2d..1d4edf193d 100644 --- a/go.sum +++ b/go.sum @@ -141,10 +141,8 @@ github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/flashbots/go-boost-utils v0.1.2 h1:xcwO6rhLmdbZ+ttN8PjHQynqY1pm+RCA56eGP9wPp10= -github.com/flashbots/go-boost-utils v0.1.2/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= -github.com/flashbots/go-boost-utils v0.1.3-0.20220601173756-01db408b8c89 h1:3wVzFGJbXm8BjuFav3ZPKFAz01IY6JDjV38b3Ccuk2I= -github.com/flashbots/go-boost-utils v0.1.3-0.20220601173756-01db408b8c89/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= +github.com/flashbots/go-boost-utils v0.1.3-0.20220601182529-417a64679a5d h1:hoqkcRKMupXCWW38fDfvNcuIxl9eCAZrguw3dNCw+Qg= +github.com/flashbots/go-boost-utils v0.1.3-0.20220601182529-417a64679a5d/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= github.com/flashbots/go-utils v0.4.4 h1:J0LUifVEpVYE+ZbK/DeGay4E3B6+Yh8pKLgfv5A0Oq0= github.com/flashbots/go-utils v0.4.4/go.mod h1:weSbiNnH+xsmK8t3TDDJxluv4+qnwRWmKay2QQa8Yfc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= From 6fbef37f31e6eb797b0675e0a57fbe6796aa2ce6 Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Fri, 3 Jun 2022 10:34:22 +0200 Subject: [PATCH 04/83] Adjust base fee encoding (#5) --- builder/backend.go | 2 +- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/builder/backend.go b/builder/backend.go index 7597666d57..d014a7efb2 100644 --- a/builder/backend.go +++ b/builder/backend.go @@ -412,7 +412,7 @@ func executableDataToExecutionPayload(data *beacon.ExecutableDataV1) *boostTypes GasUsed: data.GasUsed, Timestamp: data.Timestamp, ExtraData: data.ExtraData, - BaseFeePerGas: [32]byte(common.BytesToHash(data.BaseFeePerGas.Bytes())), + BaseFeePerGas: *new(boostTypes.U256Str).FromBig(data.BaseFeePerGas), BlockHash: [32]byte(data.BlockHash), Transactions: transactionData, } diff --git a/go.mod b/go.mod index 99146f88a4..a63f7763fa 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/fatih/color v1.9.0 github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 - github.com/flashbots/go-boost-utils v0.1.3-0.20220601182529-417a64679a5d + github.com/flashbots/go-boost-utils v0.1.3-0.20220602181853-0b5ffd891e10 github.com/flashbots/go-utils v0.4.4 github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 github.com/go-stack/stack v1.8.0 diff --git a/go.sum b/go.sum index 1d4edf193d..f8ee19d494 100644 --- a/go.sum +++ b/go.sum @@ -143,6 +143,8 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlK github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flashbots/go-boost-utils v0.1.3-0.20220601182529-417a64679a5d h1:hoqkcRKMupXCWW38fDfvNcuIxl9eCAZrguw3dNCw+Qg= github.com/flashbots/go-boost-utils v0.1.3-0.20220601182529-417a64679a5d/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= +github.com/flashbots/go-boost-utils v0.1.3-0.20220602181853-0b5ffd891e10 h1:3fbCrMmSOayxCHNkIVUWLFR+q/dR1KeXUD08OXhShBM= +github.com/flashbots/go-boost-utils v0.1.3-0.20220602181853-0b5ffd891e10/go.mod h1:v4f01OjPm5jFjzVhcJEKHLFZzX/yTeme9284Tbuah8s= github.com/flashbots/go-utils v0.4.4 h1:J0LUifVEpVYE+ZbK/DeGay4E3B6+Yh8pKLgfv5A0Oq0= github.com/flashbots/go-utils v0.4.4/go.mod h1:weSbiNnH+xsmK8t3TDDJxluv4+qnwRWmKay2QQa8Yfc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= From b67d952a92737e20f50b4fb729b4f76e379c6ebb Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Tue, 7 Jun 2022 12:09:57 +0200 Subject: [PATCH 05/83] Allow resending of the same validator registration (#7) --- builder/backend.go | 7 ++++++- builder/backend_test.go | 3 +-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/builder/backend.go b/builder/backend.go index d014a7efb2..77fdbc2b31 100644 --- a/builder/backend.go +++ b/builder/backend.go @@ -182,7 +182,12 @@ func (b *Backend) handleRegisterValidator(w http.ResponseWriter, req *http.Reque for _, registerRequest := range payload { pubkeyHex := PubkeyHex(registerRequest.Message.Pubkey.String()) if previousValidatorData, ok := b.validators[pubkeyHex]; ok { - if registerRequest.Message.Timestamp <= previousValidatorData.Timestamp { + if registerRequest.Message.Timestamp < previousValidatorData.Timestamp { + respondError(w, http.StatusBadRequest, "invalid timestamp") + return + } + + if registerRequest.Message.Timestamp == previousValidatorData.Timestamp && (registerRequest.Message.FeeRecipient != previousValidatorData.FeeRecipient || registerRequest.Message.GasLimit != previousValidatorData.GasLimit) { respondError(w, http.StatusBadRequest, "invalid timestamp") return } diff --git a/builder/backend_test.go b/builder/backend_test.go index 1158d06f25..762903f923 100644 --- a/builder/backend_test.go +++ b/builder/backend_test.go @@ -64,8 +64,7 @@ func TestValidatorRegistration(t *testing.T) { require.Equal(t, ValidatorData{FeeRecipient: payload[0].Message.FeeRecipient, GasLimit: payload[0].Message.GasLimit, Timestamp: payload[0].Message.Timestamp}, backend.validators[PubkeyHex(v.Pk.String())]) rr = testRequest(t, backend, "POST", "/eth/v1/builder/validators", payload) - require.Equal(t, http.StatusBadRequest, rr.Code) - require.Equal(t, `{"code":400,"message":"invalid timestamp"}`+"\n", rr.Body.String()) + require.Equal(t, http.StatusOK, rr.Code) payload[0].Message.Timestamp += 1 // Invalid signature From 28fd947efda723c658360d7829782f7c694b2b0b Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Fri, 10 Jun 2022 14:26:32 +0200 Subject: [PATCH 06/83] Adjust value encoding (#9) --- builder/backend.go | 3 +-- builder/backend_test.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/builder/backend.go b/builder/backend.go index 77fdbc2b31..917222d197 100644 --- a/builder/backend.go +++ b/builder/backend.go @@ -11,7 +11,6 @@ import ( "sync" "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/beacon" "github.com/ethereum/go-ethereum/core/types" @@ -248,7 +247,7 @@ func (b *Backend) handleGetHeader(w http.ResponseWriter, req *http.Request) { bid := boostTypes.BuilderBid{ Header: bestHeader, - Value: [32]byte(common.BytesToHash(profit.Bytes())), + Value: *new(boostTypes.U256Str).FromBig(profit), Pubkey: b.builderPublicKey, } signature, err := boostTypes.SignMessage(&bid, b.builderSigningDomain, b.builderSecretKey) diff --git a/builder/backend_test.go b/builder/backend_test.go index 762903f923..cd6a508000 100644 --- a/builder/backend_test.go +++ b/builder/backend_test.go @@ -150,7 +150,7 @@ func TestGetHeader(t *testing.T) { require.NoError(t, err) require.EqualValues(t, &boostTypes.BuilderBid{ Header: expectedHeader, - Value: [32]byte(common.BytesToHash(forkchoiceBlock.Profit.Bytes())), + Value: *new(boostTypes.U256Str).FromBig(forkchoiceBlock.Profit), Pubkey: backend.builderPublicKey, }, bid.Data.Message) From 3f1283142a984f90893e791827d1cc7a71856413 Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Fri, 10 Jun 2022 14:26:43 +0200 Subject: [PATCH 07/83] Adjust gas limit calculation (#8) --- miner/worker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner/worker.go b/miner/worker.go index be9e87fcb8..5e14383406 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1012,7 +1012,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent.Header()) if !w.chainConfig.IsLondon(parent.Number()) { parentGasLimit := parent.GasLimit() * params.ElasticityMultiplier - header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil) + header.GasLimit = core.CalcGasLimit(parentGasLimit, gasTarget) } } // Run the consensus preparation with the default or customized consensus engine. From 0b356f240cba80decbec912a462001cee913f1a2 Mon Sep 17 00:00:00 2001 From: Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> Date: Fri, 10 Jun 2022 18:11:39 +0200 Subject: [PATCH 08/83] Show builder pubkey on index page (#10) --- builder/backend.go | 24 +++++++++++++++++++----- builder/backend_test.go | 7 ++++++- builder/index.go | 16 ++++++++++++++++ builder/service.go | 2 +- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/builder/backend.go b/builder/backend.go index 917222d197..09c145c08d 100644 --- a/builder/backend.go +++ b/builder/backend.go @@ -41,6 +41,7 @@ type Backend struct { builderSecretKey *bls.SecretKey builderPublicKey boostTypes.PublicKey serializedBuilderPoolPubkey hexutil.Bytes + fd ForkData builderSigningDomain boostTypes.Domain proposerSigningDomain boostTypes.Domain enableBeaconChecks bool @@ -56,7 +57,13 @@ type Backend struct { indexTemplate *template.Template } -func NewBackend(sk *bls.SecretKey, bc IBeaconClient, builderSigningDomain boostTypes.Domain, proposerSigningDomain boostTypes.Domain, enableBeaconChecks bool) *Backend { +type ForkData struct { + GenesisForkVersion string + BellatrixForkVersion string + GenesisValidatorsRoot string +} + +func NewBackend(sk *bls.SecretKey, bc IBeaconClient, fd ForkData, builderSigningDomain boostTypes.Domain, proposerSigningDomain boostTypes.Domain, enableBeaconChecks bool) *Backend { pkBytes := bls.PublicKeyFromSecretKey(sk).Compress() pk := boostTypes.PublicKey{} pk.FromSlice(pkBytes) @@ -77,6 +84,7 @@ func NewBackend(sk *bls.SecretKey, bc IBeaconClient, builderSigningDomain boostT builderPublicKey: pk, serializedBuilderPoolPubkey: pkBytes, + fd: fd, builderSigningDomain: builderSigningDomain, proposerSigningDomain: proposerSigningDomain, enableBeaconChecks: enableBeaconChecks, @@ -107,10 +115,16 @@ func (b *Backend) handleIndex(w http.ResponseWriter, req *http.Request) { } statusData := struct { - NoValidators int - Header string - Blocks string - }{noValidators, string(headerData), string(payloadData)} + Pubkey string + NoValidators int + GenesisForkVersion string + BellatrixForkVersion string + GenesisValidatorsRoot string + BuilderSigningDomain string + ProposerSigningDomain string + Header string + Blocks string + }{hexutil.Encode(b.serializedBuilderPoolPubkey), noValidators, b.fd.GenesisForkVersion, b.fd.BellatrixForkVersion, b.fd.GenesisValidatorsRoot, hexutil.Encode(b.builderSigningDomain[:]), hexutil.Encode(b.proposerSigningDomain[:]), string(headerData), string(payloadData)} if err := b.indexTemplate.Execute(w, statusData); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/builder/backend_test.go b/builder/backend_test.go index cd6a508000..9880f5cb8e 100644 --- a/builder/backend_test.go +++ b/builder/backend_test.go @@ -26,7 +26,7 @@ func newTestBackend(t *testing.T) (*Backend, *ValidatorPrivateData) { bDomain := boostTypes.ComputeDomain(boostTypes.DomainTypeAppBuilder, [4]byte{0x02, 0x0, 0x0, 0x0}, boostTypes.Hash{}) genesisValidatorsRoot := boostTypes.Hash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")) cDomain := boostTypes.ComputeDomain(boostTypes.DomainTypeBeaconProposer, [4]byte{0x02, 0x0, 0x0, 0x0}, genesisValidatorsRoot) - backend := NewBackend(sk, &testBeaconClient{validator}, bDomain, cDomain, true) + backend := NewBackend(sk, &testBeaconClient{validator}, ForkData{}, bDomain, cDomain, true) // service := NewService("127.0.0.1:31545", backend) return backend, validator @@ -231,3 +231,8 @@ func TestGetPayload(t *testing.T) { require.NoError(t, err) require.Equal(t, bid.Data.Message.Header.BlockHash, getPayloadResponse.Data.BlockHash) } + +func TestXxx(t *testing.T) { + sk, _ := bls.GenerateRandomSecretKey() + fmt.Println(hexutil.Encode(sk.Serialize())) +} diff --git a/builder/index.go b/builder/index.go index 6e1e02e4db..c65d248353 100644 --- a/builder/index.go +++ b/builder/index.go @@ -46,6 +46,22 @@ func parseIndexTemplate() (*template.Template, error) {

Boost Block Builder

+

+ Pubkey {{ .Pubkey }} +

+

+

    +
  • Genesis fork version {{ .GenesisForkVersion }}
  • +
  • Bellatrix fork version {{ .BellatrixForkVersion }}
  • +
  • Genesis validators root {{ .GenesisValidatorsRoot }}
  • +
+

+

+

    +
  • Builder signing domain {{ .BuilderSigningDomain }}
  • +
  • Proposer signing domain {{ .ProposerSigningDomain }}
  • +
+