Merge branch 'master' into algolia
This commit is contained in:
commit
9d9735a252
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
title: Contributing
|
||||
description: Guidlines for contributing to Geth
|
||||
description: Guidelines for contributing to Geth
|
||||
---
|
||||
|
||||
We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
|
||||
|
||||
## Contributing to the Geth source code
|
||||
## Contributing to the Geth source code {#contributing-to-source-code}
|
||||
|
||||
If you'd like to contribute to the Geth source code, please fork the [Github repository](https://github.com/ethereum/go-ethereum), 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 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.
|
||||
|
||||
|
@ -23,11 +23,11 @@ All pull requests will be reviewed according to the [Code Review guidelines](/do
|
|||
|
||||
We encourage an early pull request approach, meaning pull requests are created as early as possible even without the completed fix/feature. This will let core devs and other volunteers know you picked up an issue. These early PRs should indicate 'in progress' status.
|
||||
|
||||
## Contributing to the Geth website
|
||||
## Contributing to the Geth website {#contributing-to-website}
|
||||
|
||||
The Geth website is hosted separately from Geth itself. The contribution guidelines are the same. Please for the Geth website Github repository and raise pull requests for the maintainers to review and merge.
|
||||
|
||||
## License
|
||||
## License {#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, also included in our repository in the COPYING.LESSER file.
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@ description: Introduction to mobile development with Geth
|
|||
Embedding clients into mobile devices is an important part of Ethereum's decentralization vision. This is because being able to verify data, follow the chain and submit transactions without relying on centralized intermediaries is critical for censorship resistant access to the network. Doing so on a mobile device is the most convenient route for many users. This relies on Geth running a [light client](/docs/interface/les) on the mobile
|
||||
device and exposing an API that developers can use to build mobile apps on top of Geth. This page outlines how to download Geth for mobile and how to get started with managing Ethereum accounts in mobile applications. Ethereum mobile development is relatively nascent, but there is an active developer community. For further information on Geth mobile development visit the #mobile channel in the [Geth discord](https://discord.gg/wQdpS5aA).
|
||||
|
||||
## Download and install
|
||||
## Download and install {#download-and-install}
|
||||
|
||||
### Android
|
||||
### Android {#android}
|
||||
|
||||
#### Android Studio
|
||||
#### Android Studio {#android-studio}
|
||||
|
||||
Geth for Mobile bundles can be downloaded directly from [the download page](/downloads) and inserted into a project in Android Studio via `File -> New -> New module... -> Import .JAR/.AAR Package`.
|
||||
|
||||
|
@ -23,7 +23,7 @@ dependencies {
|
|||
}
|
||||
```
|
||||
|
||||
#### Manual build
|
||||
#### Manual build {#manual-build}
|
||||
|
||||
Geth can also be built it locally using a `make` command. This will create an Android archive called `geth.aar` in the `build/bin` folder that can be imported into Android Studio as described above.
|
||||
|
||||
|
@ -34,7 +34,7 @@ Done building.
|
|||
Import "build/bin/geth.aar" to use the library.
|
||||
```
|
||||
|
||||
### iOS
|
||||
### iOS {#ios}
|
||||
|
||||
Geth must be downloaded and built locally for IoS. Building locally is achieved using the `make` command. This will create an iOS XCode framework called `Geth.framework` in the `build/bin` folder that can be imported into XCode as described above.
|
||||
|
||||
|
@ -45,7 +45,7 @@ Done building.
|
|||
Import "build/bin/Geth.framework" to use the library.
|
||||
```
|
||||
|
||||
## Mobile API
|
||||
## Mobile API {#mobile-api}
|
||||
|
||||
Similarly to the reusable [Go libraries](/docs/developers/dapp-developer/native-accounts), the mobile wrappers focus on three main usage areas:
|
||||
|
||||
|
@ -56,14 +56,14 @@ Similarly to the reusable [Go libraries](/docs/developers/dapp-developer/native-
|
|||
The Geth mobile API is broadly equivalent to the [Go API](/docs/developers/dapp-developer/native-accounts). The source code can be found in the `mobile` section of Geth's
|
||||
[Github](https://github.com/ethereum/go-ethereum/tree/master/mobile).
|
||||
|
||||
## Mobile Account Management
|
||||
## Mobile Account Management {#mobile-account-management}
|
||||
|
||||
Best practise for account management is to do it client-side, with all sensitive information self-contained inside the local application. This ensures the developer/user retains fine-grained control over the access permissions for user-data instead of outsourcing security
|
||||
to a third party.
|
||||
|
||||
To support this, Geth provides an accounts library that includes the tools required for secure account management via encrypted keystores and passphrase protected accounts, similarly to running a full Geth node.
|
||||
|
||||
### Encrypted keystores
|
||||
### Encrypted keystores {#encrypted-keystores}
|
||||
|
||||
Access keys to Ethereum accounts should never be stored in plain-text. Instead, they should be stored encrypted so that even if the mobile device is accessed by a malicious third party the keys are still hidden under an additional layer of security. Geth provides a keystore that enables developers to store keys securely using the [`secp256k1` elliptic curve](https://www.secg.org/sec2-v2.pdf), implemented using [`libsecp256k`](https://github.com/bitcoin-core/secp256k1) and wrapped by [Geth accounts](https://godoc.org/github.com/ethereum/go-ethereum/accounts).
|
||||
|
||||
|
@ -75,7 +75,7 @@ should be aware that there is a security trade-off.
|
|||
- _standard_ needs 256MB memory and 1 second processing on a modern CPU to access a key
|
||||
- _light_ needs 4MB memory and 100 millisecond processing on a modern CPU to access a key
|
||||
|
||||
### Keystores on Android (Java)
|
||||
### Keystores on Android (Java) {#keystores-on-android}
|
||||
|
||||
The encrypted keystore on Android is implemented by the `KeyStore` class from the `org.ethereum.geth` package. The configuration constants are located in the `Geth` abstract class, similarly from the `org.ethereum.geth` package. Hence to do client side account management on Android, two classes should be imported into the Java code:
|
||||
|
||||
|
@ -94,7 +94,7 @@ The keystore should be in a location writable by the local mobile application bu
|
|||
|
||||
The last two arguments of the `KeyStore` constructor are the crypto parameters defining how resource-intensive the keystore encryption should be. The choices are `Geth.StandardScryptN, Geth.StandardScryptP`, `Geth.LightScryptN, Geth.LightScryptP` or custom numbers. The _light_ version is recommended.
|
||||
|
||||
### Keystores on iOS (Swift 3)
|
||||
### Keystores on iOS (Swift 3) {#keystores-on-ios}
|
||||
|
||||
The encrypted keystore on iOS is implemented by the `GethKeyStore` class from the `Geth` framework. The configuration constants are located in the same namespace as global variables. Hence to do client side account management on iOS, `Geth` framework should be
|
||||
imported into the Swift code:
|
||||
|
@ -114,7 +114,7 @@ The keystore folder needs to be in a location writable by the local mobile appli
|
|||
|
||||
The last two arguments of the `GethNewKeyStore` factory method are the crypto parameters defining how resource-intensive the keystore encryption should be. The choices are `GethStandardScryptN, GethStandardScryptP`, `GethLightScryptN, GethLightScryptP` or custom numbers. The _light_ version is recommended.
|
||||
|
||||
### Account lifecycle
|
||||
### Account lifecycle {#account-lifecycle}
|
||||
|
||||
The encyrpted keystore can be used for the entire account lifecycle requirements of a mobile application. This includes the basic functionality of creating new accounts and deleting existing ones as well as more advanced functions like updating access credentials and account
|
||||
import/export.
|
||||
|
@ -131,7 +131,7 @@ This individuality means that any operation requiring access to an account will
|
|||
|
||||
_Please note, there is no recovery mechanisms for losing the passphrases. The cryptographic properties of the encrypted keystore (if using the provided parameters) guarantee that account credentials cannot be brute forced in any meaningful time._
|
||||
|
||||
### Accounts on Android (Java)
|
||||
### Accounts on Android (Java) {#accounts-on-android}
|
||||
|
||||
An Ethereum account on Android is implemented by the `Account` class from the `org.ethereum.geth` package. Assuming an instance of a `KeyStore` called `ks` exists, all of the described lifecycle operations can be executed with a handful of function calls:
|
||||
|
||||
|
@ -156,7 +156,7 @@ Account impAcc = ks.importKey(jsonAcc, "Export password", "Import password");
|
|||
|
||||
Although instances of `Account` can be used to access various information about specific Ethereum accounts, they do not contain any sensitive data (such as passphrases or private keys), rather they act solely as identifiers for client code and the keystore.
|
||||
|
||||
### Accounts on iOS (Swift 3)
|
||||
### Accounts on iOS (Swift 3) {#accounts-on-ios}
|
||||
|
||||
An Ethereum account on iOS is implemented by the `GethAccount` class from the `Geth` framework. Assuming an instance of a `GethKeyStore` called `ks` exists, all of the described lifecycle operations can be executed with a handful of function calls:
|
||||
|
||||
|
@ -181,7 +181,7 @@ let impAcc = try! ks?.importKey(jsonKey, passphrase: "Export password", newPass
|
|||
|
||||
Although instances of `GethAccount` can be used to access various information about specific Ethereum accounts, they do not contain any sensitive data (such as passphrases or private keys), rather they act solely as identifiers for client code and the keystore.
|
||||
|
||||
## Signing authorization
|
||||
## Signing authorization {#signing-authorization}
|
||||
|
||||
As mentioned above, account objects do not hold the sensitive private keys of the associated Ethereum accounts - they are merely placeholders to identify the cryptographic keys with. All operations that require authorization (e.g. transaction signing) are performed by the account manager after granting it access to the private keys.
|
||||
|
||||
|
@ -191,7 +191,7 @@ There are a few different ways one can authorize the account manager to execute
|
|||
|
||||
- **Multiple authorizations**: A more complex way of signing transactions via the keystore is to unlock the account via its passphrase once, and allow the account manager to cache the decrypted private key, enabling all subsequent signing requests tocomplete without the passphrase. The lifetime of the cached private key may be managed manually (by explicitly locking the account back up) or automatically (by providing a timeout during unlock). This mechanism is useful for scenarios where the user may need to sign many transactions or the application would need to do so without requiring user input. The crucial aspect to remember is that **anyone with access to the account manager can sign transactions while a particular account is unlocked** (e.g. device left unattended; application running untrusted code).
|
||||
|
||||
### Signing on Android (Java)
|
||||
### Signing on Android (Java) {#signing-on-android}
|
||||
|
||||
Assuming an instance of a `KeyStore` called `ks` exists, a new account to sign transactions can be created using its `newAccount` method. For this demonstation a hard-coded example transaction is created to sign:
|
||||
|
||||
|
@ -220,7 +220,7 @@ ks.timedUnlock(signer, "Signer password", 1000000000);
|
|||
signed = ks.signTx(signer, tx, chain);
|
||||
```
|
||||
|
||||
### Signing on iOS (Swift 3)
|
||||
### Signing on iOS (Swift 3) {#signing-on-ios}
|
||||
|
||||
Assuming an instance of a `GethKeyStore` called `ks` exists, a new account can be created to sign transactions with its `newAccount` method. For
|
||||
this demonstation a hard-coded example transaction is created to sign:
|
||||
|
@ -251,6 +251,6 @@ try! ks?.timedUnlock(signer, passphrase: "Signer password", timeout: 1000000000)
|
|||
signed = try! ks?.signTx(signer, tx: tx, chainID: chain)
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page introduced Geth for mobile. In addition to download and installation instructions, basic account management was demonstrated for mobile applications on iOS and Android.
|
||||
|
|
|
@ -7,7 +7,7 @@ Geth provides a simple, yet thorough accounts package that includes all the tool
|
|||
|
||||
**Note Geth's built-in account management is convenient and straightforward to use, but best practise is to use the external tool _Clef_ for key management.**
|
||||
|
||||
## Encrypted keystores
|
||||
## Encrypted keystores {#encrypted-keystores}
|
||||
|
||||
Access keys to Ethereum accounts should never be stored in plain-text. Instead, they should be stored encrypted so that even if the mobile device is accessed by a malicious third party the keys are still hidden under an additional layer of security. Geth provides a keystore that enables developers to store keys securely. The Geth keystore uses [Scrypt](https://pkg.go.dev/golang.org/x/crypto/scrypt) to store keys that are encoded using the [`secp256k1`](https://www.secg.org/sec2-v2.pdf) elliptic curve. Accounts are stored on disk in the [Web3 Secret Storage](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) format. Developers should be aware of these implementation details
|
||||
but are not required to deeply understand the cryptographic primitives in order to use the keystore.
|
||||
|
@ -37,7 +37,7 @@ The path to the keystore folder needs to be a location that is writable by the l
|
|||
|
||||
The last two arguments of [`keystore.NewKeyStore`](https://godoc.org/github.com/ethereum/go-ethereum/accounts/keystore#NewKeyStore) are the crypto parameters defining how resource-intensive the keystore encryption should be. The options are [`accounts.StandardScryptN, accounts.StandardScryptP`, `accounts.LightScryptN, accounts.LightScryptP`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#pkg-constants) or custom values (requiring understanding of the underlying cryptography). The _standard_ version is recommended.
|
||||
|
||||
## Account lifecycle
|
||||
## Account lifecycle {#account-lifecycle}
|
||||
|
||||
Once an encrypted keystore for Ethereum accounts exists it, it can be used to manage accounts for the entire account lifecycle requirements of a Go native application. This includes the basic functionality of creating new accounts and deleting existing ones as well as updating access credentials, exporting existing accounts, and importing them on other devices.
|
||||
|
||||
|
@ -81,7 +81,7 @@ impAcc, _ := ks.Import(jsonAcc, "Export password", "Import password")
|
|||
|
||||
_Although instances of [`accounts.Account`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#Account) can be used to access various information about specific Ethereum accounts, they do not contain any sensitive data (such as passphrases or private keys), rather they act solely as identifiers for client code and the keystore._
|
||||
|
||||
## Signing authorization
|
||||
## Signing authorization {#signing-authorization}
|
||||
|
||||
Account objects do not hold the sensitive private keys of the associated Ethereum accounts. Account objects are placeholders that identify the cryptographic keys. All operations that require authorization (e.g. transaction signing) are performed by the account manager after granting it access to the private keys.
|
||||
|
||||
|
@ -119,6 +119,6 @@ signature, _ = ks.SignHash(signer, txHash.Bytes())
|
|||
|
||||
Note that [`SignWithPassphrase`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#Manager.SignWithPassphrase) takes an [`accounts.Account`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#Account) as the signer, whereas [`Sign`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#Manager.Sign) takes only a [`common.Address`](https://godoc.org/github.com/ethereum/go-ethereum/common#Address). The reason for this is that an [`accounts.Account`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#Account) object may also contain a custom key-path, allowing [`SignWithPassphrase`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#Manager.SignWithPassphrase) to sign using accounts outside of the keystore; however [`Sign`](https://godoc.org/github.com/ethereum/go-ethereum/accounts#Manager.Sign) relies on accounts already unlocked within the keystore, so it cannot specify custom paths.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Account management is a fundamental pillar of Ethereum development. Geth's Go API provides the tools required to integrate best-practise account security into Go native applications using a simple set of Go functions.
|
||||
|
|
|
@ -9,15 +9,15 @@ Interacting with a contract on the Ethereum blockchain from Go is already possib
|
|||
|
||||
This page provides an introduction to generating Go contract bindings and using them in a simple Go application.
|
||||
|
||||
## Prerequisites
|
||||
## Prerequisites {#prerequisites}
|
||||
|
||||
This page is fairly beginner-friendly and designed for people starting out with writing Go native dapps. The core concepts will be introduced gradually as a developer would encounter them. However, some basic familiarity with [Ethereum](https://ethereum.org), [Solidity](https://docs.soliditylang.org/en/v0.8.15/) and [Go](https://go.dev/) is assumed.
|
||||
|
||||
## What is an ABI?
|
||||
## What is an ABI? {#what-is-an-abi}
|
||||
|
||||
Ethereum smart contracts have a schema that defines its functions and return types in the form of a JSON file. This JSON file is known as an _Application Binary Interface_, or ABI. The ABI acts as a specification for precisely how to encode data sent to a contract and how to decode the data the contract sends back. The ABI is the only essential piece of information required to generate Go bindings. Go developers can then use the bindings to interact with the contract from their Go application without having to deal directly with data encoding and decoding. An ABI is generated when a contract is compiled.
|
||||
|
||||
## Abigen: Go binding generator
|
||||
## Abigen: Go binding generator {#abigen}
|
||||
|
||||
Geth includes a source code generator called `abigen` that can convert Ethereum ABI definitions into easy to use, type-safe Go packages. With a valid Go development environment set up and the go-ethereum repository checked out correctly, `abigen` can be built as follows:
|
||||
|
||||
|
@ -26,7 +26,7 @@ $ cd $GOPATH/src/github.com/ethereum/go-ethereum
|
|||
$ go build ./cmd/abigen
|
||||
```
|
||||
|
||||
### Generating the bindings
|
||||
### Generating the bindings {#generating-bindings}
|
||||
|
||||
To demonstrate the binding generator a contract is required. The contract `Storage.sol` implements two very simple functions: `store` updates a user-defined `uint256` to the contract's storage, and `retrieve` displays the value stored in the contract to the user. The Solidity code is as follows:
|
||||
|
||||
|
@ -152,7 +152,7 @@ type Storage struct {
|
|||
`Storage.go` contains all the bindings required to interact with `Storage.sol` from a Go application. However, this isn't very useful unless the contract is actually deployed on Ethereum or one of Ethereum's testnets. The following sections will demonstrate how to deploy the contract to
|
||||
an Ethereum testnet and interact with it using the Go bindings.
|
||||
|
||||
### Deploying contracts to Ethereum
|
||||
### Deploying contracts to Ethereum {#deploying-contracts}
|
||||
|
||||
In the previous section, the contract ABI was sufficient for generating the contract bindings from its ABI. However, deploying the contract requires some additional information in the form of the compiled bytecode.
|
||||
|
||||
|
@ -267,7 +267,7 @@ Note that `DeployStorage` returns four variables:
|
|||
|
||||
- `err`: a variable that handles errors in case of a deployment failure
|
||||
|
||||
### Accessing an Ethereum contract
|
||||
### Accessing an Ethereum contract {#accessing-contracts}
|
||||
|
||||
To interact with a contract already deployed on the blockchain, the deployment `address` is required and a `backend` through which to access Ethereum must be defined. The binding generator provides an RPC backend out-of-the-box that can be used to attach to an existing Ethereum node via IPC, HTTP or WebSockets.
|
||||
|
||||
|
@ -369,7 +369,7 @@ The output will be something like:
|
|||
Value: 56
|
||||
```
|
||||
|
||||
### Transacting with an Ethereum contract
|
||||
### Transacting with an Ethereum contract {#transacting-with-contract}
|
||||
|
||||
Invoking a method that changes contract state (i.e. transacting) is a bit more involved, as a live transaction needs to be authorized and broadcast into the network. **Go bindings require local signing of transactions and do not delegate this to a remote node.** This is to keep accounts private within dapps, and not shared (by default) between them.
|
||||
|
||||
|
@ -434,7 +434,7 @@ Similar to the method invocations in the previous section which only read contra
|
|||
|
||||
The two mandatory fields are automatically set by the `bind` package if the auth options are constructed using `bind.NewTransactor`. The nonce and gas related fields are automatically derived by the binding if they are not set. Unset values are assumed to be zero.
|
||||
|
||||
### Pre-configured contract sessions
|
||||
### Pre-configured contract sessions {#preconfigured-sessions}
|
||||
|
||||
Reading and state modifying contract-calls require a mandatory first parameter which can authorize and fine tune some of the internal parameters. However, most of the time the same accounts and parameters will be used to issue many transactions, so constructing the call/transact options individually quickly becomes unwieldy.
|
||||
|
||||
|
@ -459,7 +459,7 @@ session := &StorageSession{
|
|||
session.Store(big.NewInt(69))
|
||||
```
|
||||
|
||||
## Bind Solidity directly
|
||||
## Bind Solidity directly {#binding-solidity}
|
||||
|
||||
In the past, abigen allowed compilation and binding of a Solidity source file directly to a Go package in a single step. This feature has been discontinued from [v1.10.18](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.18) onwards due to maintenance synchronization challenges with the compiler in Geth.
|
||||
|
||||
|
@ -469,7 +469,7 @@ The compilation and binding steps can be joined together into a pipeline, for ex
|
|||
solc Storage.sol --combined-json abi,bin | abigen --pkg main --type storage --out Storage.go --combined-json -
|
||||
```
|
||||
|
||||
### Project integration (`go generate`)
|
||||
### Project integration (`go generate`) {#project-integration}
|
||||
|
||||
The `abigen` command was made in such a way as to integrate easily into existing Go toolchains: instead of having to remember the exact command needed to bind an Ethereum contract into a Go project, `go generate` can handle all the fine details.
|
||||
|
||||
|
@ -481,7 +481,7 @@ Place the binding generation command into a Go source file before the package de
|
|||
|
||||
After which whenever the Solidity contract is modified, instead of needing to remember and run the above command, we can simply call `go generate` on the package (or even the entire source tree via `go generate ./...`), and it will correctly generate the new bindings for us.
|
||||
|
||||
## Blockchain simulator
|
||||
## Blockchain simulator {#blockchain-simulator}
|
||||
|
||||
Being able to deploy and access deployed Ethereum contracts from native Go code is a powerful feature. However, using public testnets as a backend does not lend itself well to _automated unit testing_. Therefore, Geth also implements a _simulated blockchain_ that can be set as a backend to native contracts the same way as a live RPC backend, using the command `backends.NewSimulatedBackend(genesisAccounts)`. The code snippet below shows how this can be used as a backend in a Go application.
|
||||
|
||||
|
@ -525,6 +525,6 @@ func main() {
|
|||
}
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
To make interacting with Ethereum contracts easier for Go developers, Geth provides tools that generate contract bindings automatically. This makes contract functions available in Go native applications.
|
||||
|
|
|
@ -13,7 +13,7 @@ This page provides a high-level overview of the Go API.
|
|||
|
||||
_Note, this guide will assume some familiarity with Go development. It does not cover general topics about Go project layouts, import paths or any other standard methodologies. If you are new to Go, consider reading [Getting Started with Go](https://github.com/golang/go/wiki#getting-started-with-go) first._
|
||||
|
||||
## Overview
|
||||
## Overview {#overview}
|
||||
|
||||
Geth's reusable Go libraries focus on three main usage areas:
|
||||
|
||||
|
@ -27,7 +27,7 @@ Péter Szilágyi (@karalabe) gave a high level overview of the Go libraries in a
|
|||
|
||||
[![Peter's Devcon2 talk](/images/docs/devcon2_labelled.webp)](https://www.youtube.com/watch?v=R0Ia1U9Gxjg)
|
||||
|
||||
## Go packages
|
||||
## Go packages {#go-packages}
|
||||
|
||||
The `go-ethereum` library is distributed as a collection of standard Go packages straight from go-ethereum's GitHub repository. The packages can be used directly via the official Go toolkit, without needing any third party tools.
|
||||
|
||||
|
@ -41,11 +41,11 @@ $ go get -d github.com/ethereum/go-ethereum/...
|
|||
|
||||
More Go API support for dapp developers can be found on the [Go Contract Bindings](/docs/developers/dapp-developer/native-bindings) and [Go Account Management](/docs/dapp/native-accounts) pages.
|
||||
|
||||
## Tutorial
|
||||
## Tutorial {#tutorial}
|
||||
|
||||
This section includes some basic usage examples for the `ethclient` and `gethclient` packages available as part of the Go API. The `ethclient` package provides a client that implements the full Ethereum JSON-RPC API, whereas `gethclient` offers the Geth-specific API.
|
||||
|
||||
### Instantiating a client
|
||||
### Instantiating a client {#instantiating-a-client}
|
||||
|
||||
The client is an instance of the `Client` struct which has associated functions that wrap requests to the Ethereum or Geth RPC API endpoints.
|
||||
|
||||
|
@ -60,13 +60,13 @@ if err != nil {
|
|||
_ = cl
|
||||
```
|
||||
|
||||
### Interacting with the client
|
||||
### Interacting with the client {#interacting-with-a-client}
|
||||
|
||||
The client can now be used to handle requests to the Geth node using the full JSON-RPC API. For example, the function `BlockNumer()` wraps a call to the `eth_blockNumber` endpoint. The function `SendTransaction` wraps a call to `eth_sendTransaction`. The full list of client methods can be found [here](https://pkg.go.dev/github.com/ethereum/go-ethereum/ethclient#Client).
|
||||
|
||||
Frequently, the functions take an instance of the `Context` type as their leading argument. This defines context about requests sent from the application such as deadlines, cancellation signals etc. More information on this can be found in the [Go documentation](https://pkg.go.dev/golang.org/x/net/context). An empty context instance can be created using `Context.Background()`.
|
||||
|
||||
### Querying client for data
|
||||
### Querying client for data {#querying-client-for-data}
|
||||
|
||||
A simple starting point is to fetch the chain ID from the client. This e.g. is needed when signing a transaction as is to be seen in the next section.
|
||||
|
||||
|
@ -84,7 +84,7 @@ addr := common.HexToAddress("0xb02A2EdA1b317FBd16760128836B0Ac59B560e9D")
|
|||
nonce, err := cl.NonceAt(context.Background(), addr, big.NewInt(14000000))
|
||||
```
|
||||
|
||||
### Querying past events
|
||||
### Querying past events {#querying-past-events}
|
||||
|
||||
Contracts emit events during execution which can be queried from the client. The parameters for the event one is interested in have to be filled out in the `ethereum.FilterQuery` object. This includes which event topics are of interested, from which contracts and during which range of blocks. The example below queries `Transfer` events of all ERC-20 tokens for the last 10 blocks:
|
||||
|
||||
|
@ -104,7 +104,7 @@ if err != nil {
|
|||
}
|
||||
```
|
||||
|
||||
### Sending a transaction
|
||||
### Sending a transaction {#sending-a-transaction}
|
||||
|
||||
Sending a transaction is achieved using the `SendTransaction()` function. `SendTransaction` takes an instance of `context.Context` as its leading argument and a signed transaction as its second argument. The signed transaction must be generated in advance. Building the signed transaction is a multi-stage process that requires first generating a key pair if none exists already, retrieving some chain data and defining sender and recipient
|
||||
addresses. Then these data can be collected into a transaction object and signed. The resulting signed transaction can then be passed to `SendTransaction`.
|
||||
|
@ -172,7 +172,7 @@ func sendTransaction(cl *ethclient.Client) error {
|
|||
}
|
||||
```
|
||||
|
||||
### gethclient
|
||||
### gethclient {#geth-client}
|
||||
|
||||
An instance of `gethclient` can be used in exactly the same way as `ethclient`. However, `gethclient` includes Geth-specific API methods. These additional methods are:
|
||||
|
||||
|
@ -191,6 +191,6 @@ _Note that both `ethclient` and `gethclient` have a `CallContract()` function -
|
|||
|
||||
Details relating to these endpoints can be found at [pkg.go.dev](https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.10.19/ethclient/gethclient) or the Geth [Github](https://github.com/ethereum/go-ethereum/tree/master/ethclient). The code snippets in this tutorial were adapted from a more more in-depth set of examples available on [Github](https://github.com/MariusVanDerWijden/web3go).
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
There are a wide variety of Go APIs available for dapp developers that abstract away the complexity of interacting with Ethereum using a set of composable, reusable functions provided by Geth.
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
---
|
||||
title: Basic traces
|
||||
description: Introduction to basic EVM traces
|
||||
---
|
||||
|
||||
The simplest type of transaction trace that Geth can generate are raw EVM opcode traces. For every VM instruction the transaction executes, a structured log entry is emitted, containing all contextual metadata deemed useful. This includes the _program counter_, _opcode name_, _opcode cost_, _remaining gas_, _execution depth_ and any _occurred error_. The structured logs can optionally also contain the content of the _execution stack_, _execution memory_ and _contract storage_.
|
||||
|
||||
The entire output of a raw EVM opcode trace is a JSON object having a few metadata fields: _consumed gas_, _failure status_, _return value_; and a list of _opcode entries_:
|
||||
|
||||
```json
|
||||
{
|
||||
"gas": 25523,
|
||||
"failed": false,
|
||||
"returnValue": "",
|
||||
"structLogs": []
|
||||
}
|
||||
```
|
||||
|
||||
An example log for a single opcode entry has the following format:
|
||||
|
||||
```json
|
||||
{
|
||||
"pc": 48,
|
||||
"op": "DIV",
|
||||
"gasCost": 5,
|
||||
"gas": 64532,
|
||||
"depth": 1,
|
||||
"error": null,
|
||||
"stack": [
|
||||
"00000000000000000000000000000000000000000000000000000000ffffffff",
|
||||
"0000000100000000000000000000000000000000000000000000000000000000",
|
||||
"2df07fbaabbe40e3244445af30759352e348ec8bebd4dd75467a9f29ec55d98d"
|
||||
],
|
||||
"memory": [
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000060"
|
||||
],
|
||||
"storage": {}
|
||||
}
|
||||
```
|
||||
|
||||
### Generating basic traces {#generating-basic-traces}
|
||||
|
||||
To generate a raw EVM opcode trace, Geth provides a few [RPC API endpoints](/docs/rpc/ns-debug). The most commonly used is [`debug_traceTransaction`](/docs/rpc/ns-debug#debug_tracetransaction).
|
||||
|
||||
In its simplest form, `traceTransaction` accepts a transaction hash as its only argument. It then traces the transaction, aggregates all the generated
|
||||
data and returns it as a **large** JSON object. A sample invocation from the Geth console would be:
|
||||
|
||||
```js
|
||||
debug.traceTransaction('0xfc9359e49278b7ba99f59edac0e3de49956e46e530a53c15aa71226b7aa92c6f');
|
||||
```
|
||||
|
||||
The same call can also be invoked from outside the node too via HTTP RPC (e.g. using Curl). In this case, the HTTP endpoint must be enabled in Geth using the `--http` command and the `debug` API namespace must be exposed using `--http.api=debug`.
|
||||
|
||||
```
|
||||
$ curl -H "Content-Type: application/json" -d '{"id": 1, "method": "debug_traceTransaction", "params": ["0xfc9359e49278b7ba99f59edac0e3de49956e46e530a53c15aa71226b7aa92c6f"]}' localhost:8545
|
||||
```
|
||||
|
||||
To follow along with this tutorial, transaction hashes can be found from a local Geth node (e.g. by attaching a [Javascript console](/docs/interface/javascript-console) and running `eth.getBlock('latest')` then passing a transaction hash from the returned block to `debug.traceTransaction()`) or from a block explorer (for [Mainnet](https://etherscan.io/) or a [testnet](https://goerli.etherscan.io/)).
|
||||
|
||||
It is also possible to configure the trace by passing Boolean (true/false) values for four parameters that tweak the verbosity of the trace. By default, the _EVM memory_ and _Return data_ are not reported but the _EVM stack_ and _EVM storage_ are. To report the maximum amount of data:
|
||||
|
||||
```shell
|
||||
enableMemory: true
|
||||
disableStack: false
|
||||
disableStorage: false
|
||||
enableReturnData: true
|
||||
```
|
||||
|
||||
An example call, made in the Geth Javascript console, configured to report the maximum amount of data looks as follows:
|
||||
|
||||
```js
|
||||
debug.traceTransaction('0xfc9359e49278b7ba99f59edac0e3de49956e46e530a53c15aa71226b7aa92c6f', {
|
||||
enableMemory: true,
|
||||
disableStack: false,
|
||||
disableStorage: false,
|
||||
enableReturnData: true
|
||||
});
|
||||
```
|
||||
|
||||
The above operation was run on the (now-deprecated) Rinkeby network (with a node retaining enough history), resulting in this [trace dump](https://gist.github.com/karalabe/c91f95ac57f5e57f8b950ec65ecc697f).
|
||||
|
||||
Alternatively, disabling _EVM Stack_, _EVM Memory_, _Storage_ and _Return data_ (as demonstrated in the Curl request below) results in the following, much shorter, [trace dump](https://gist.github.com/karalabe/d74a7cb33a70f2af75e7824fc772c5b4).
|
||||
|
||||
```
|
||||
$ curl -H "Content-Type: application/json" -d '{"id": 1, "method": "debug_traceTransaction", "params": ["0xfc9359e49278b7ba99f59edac0e3de49956e46e530a53c15aa71226b7aa92c6f", {"disableStack": true, "disableStorage": true}]}' localhost:8545
|
||||
```
|
||||
|
||||
### Limits of basic traces {#list-of-basic-traces}
|
||||
|
||||
Although the raw opcode traces generated above are useful, having an individual log entry for every single opcode is too low level for most use cases,
|
||||
and will require developers to create additional tools to post-process the traces. Additionally, a full opcode trace can easily go into the hundreds of megabytes, making them very resource intensive to get out of the node and process externally.
|
||||
|
||||
To avoid those issues, Geth supports running custom JavaScript tracers _within_ the Ethereum node, which have full access to the EVM stack, memory and contract storage. This means developers only have to gather the data they actually need, and do any processing at the source.
|
||||
|
||||
## Summary {#summary}
|
||||
|
||||
This page described how to do basic traces in Geth. Basic traces are very low level and can generate lots of data that might not all be useful. Therefore, it is also possible to use a set of built-in tracers or write custom ones in Javascript or Go.
|
||||
|
||||
Read more about [built-in](/docs/evm-tracing/builtin-tracers) and [custom](/docs/evm-tracing/custom-tracer) traces.
|
|
@ -5,7 +5,7 @@ description: Explanation of the tracers that come bundled in Geth as part of the
|
|||
|
||||
Geth comes bundled with a choice of tracers that can be invoked via the [tracing API](/docs/rpc/ns-debug). Some of these built-in tracers are implemented natively in Go, and others in Javascript. The default tracer is the opcode logger (otherwise known as struct logger) which is the default tracer for all the methods. Other tracers have to be specified by passing their name to the `tracer` parameter in the API call.
|
||||
|
||||
## Struct/opcode logger
|
||||
## Struct/opcode logger {#struct-opcode-logger}
|
||||
|
||||
The struct logger (aka opcode logger) is a native Go tracer which executes a transaction and emits the opcode and execution context at every step. This is the tracer that will be used when no name is passed to the API, e.g. `debug.traceTransaction(<txhash>)`. The following information is emitted at each step:
|
||||
|
||||
|
@ -89,13 +89,14 @@ Return:
|
|||
|
||||
```
|
||||
|
||||
## Native tracers
|
||||
## Native tracers {#native-tracers}
|
||||
|
||||
The following tracers are implement in Go. This means they are much more performant than other tracers that are written in Javascript. The tracers are selected by passing their name to the `tracer` parameter when invoking a tracing API method, e.g. `debug.traceTransaction(<txhash>, { tracer: 'callTracer' })`.
|
||||
|
||||
### 4byteTracer
|
||||
### 4byteTracer {#4byte-tracer}
|
||||
|
||||
Solidity contract functions are [addressed](https://docs.soliditylang.org/en/develop/abi-spec.html#function-selector) using the first four four byte of the Keccak-256 hash of their signature. Therefore when calling the function of a contract, the caller must send this function selector as well as the ABI-encoded arguments as call data.
|
||||
Solidity contract functions are
|
||||
[addressed](https://docs.soliditylang.org/en/develop/abi-spec.html#function-selector) using the first four four byte of the Keccak-256 hash of their signature. Therefore when calling the function of a contract, the caller must send this function selector as well as the ABI-encoded arguments as call data.
|
||||
|
||||
The `4byteTracer` collects the function selectors of every function executed in the lifetime of a transaction, along with the size of the supplied call data. The result is a `map[string]int` where the keys are `SELECTOR-CALLDATASIZE` and the values are number of occurances of this key. For example:
|
||||
|
||||
|
@ -117,22 +118,23 @@ Return:
|
|||
}
|
||||
```
|
||||
|
||||
### callTracer
|
||||
### callTracer {#call-tracer}
|
||||
|
||||
The `callTracer` tracks all the call frames executed during a transaction, including depth 0. The result will be a nested list of call frames, resembling how EVM works. They form a tree with the top-level call at root and sub-calls as children of the higher levels. Each call frame has the following fields:
|
||||
|
||||
| field | type | description |
|
||||
| ------- | ----------- | ------------------------------------ |
|
||||
| type | string | CALL or CREATE |
|
||||
| from | string | address |
|
||||
| to | string | address |
|
||||
| value | string | hex-encoded amount of value transfer |
|
||||
| gas | string | hex-encoded gas provided for call |
|
||||
| gasUsed | string | hex-encoded gas used during call |
|
||||
| input | string | call data |
|
||||
| output | string | return data |
|
||||
| error | string | error, if any |
|
||||
| calls | []callframe | list of sub-calls |
|
||||
| field | type | description |
|
||||
| ------------ | ----------- | ------------------------------------ |
|
||||
| type | string | CALL or CREATE |
|
||||
| from | string | address |
|
||||
| to | string | address |
|
||||
| value | string | hex-encoded amount of value transfer |
|
||||
| gas | string | hex-encoded gas provided for call |
|
||||
| gasUsed | string | hex-encoded gas used during call |
|
||||
| input | string | call data |
|
||||
| output | string | return data |
|
||||
| error | string | error, if any |
|
||||
| revertReason | string | Solidity revert reason, if any |
|
||||
| calls | []callframe | list of sub-calls |
|
||||
|
||||
Example Call:
|
||||
|
||||
|
@ -174,9 +176,23 @@ Return:
|
|||
Things to note about the call tracer:
|
||||
|
||||
- Calls to precompiles are also included in the result
|
||||
- In case a frame reverts, the field `output` will contain the raw return data, unlike [revertReasonTracer](#revertreasontracer) which parses the data and returns the revert message
|
||||
- In case a frame reverts, the field `output` will contain the raw return data
|
||||
- In case the top level frame reverts, its `revertReason` field will contain the parsed reason of revert as returned by the Solidity contract
|
||||
|
||||
### prestateTracer
|
||||
#### Config
|
||||
|
||||
`callTracer` accepts two options:
|
||||
|
||||
- `onlyTopCall: true` instructs the tracer to only process the main (top-level) call and none of the sub-calls. This avoids extra processing for each call frame if only the top-level call info are required.
|
||||
- `withLog: true` instructs the tracer to also collect the logs emitted during each call.
|
||||
|
||||
Example invokation with the `onlyTopCall` flag:
|
||||
|
||||
```terminal
|
||||
> debug.traceTransaction('0xc73e70f6d60e63a71dabf90b9983f2cdd56b0cb7bcf1a205f638d630a95bba73', { tracer: 'callTracer', tracerConfig: { onlyTopCall: true } })
|
||||
```
|
||||
|
||||
### prestateTracer {#prestate-tracer}
|
||||
|
||||
The prestate tracer has two modes: `prestate` and `diff`. The `prestate` mode returns the accounts necessary to execute a given transaction. `diff` mode returns the differences between the transaction's pre and post-state (i.e. what changed because the transaction happened). The `prestateTracer` defaults to `prestate` mode. It reexecutes the given transaction and tracks every part of state that is touched. This is similar to the concept of a [stateless witness](https://ethresear.ch/t/the-stateless-client-concept/172), the difference being this tracer doesn't return any cryptographic proof, rather only the trie leaves. The result is an object. The keys are addresses of accounts. The value is an object with the following fields:
|
||||
|
||||
|
@ -249,31 +265,15 @@ Return (same call with `{diffMode: True}`):
|
|||
}
|
||||
```
|
||||
|
||||
### revertReasonTracer
|
||||
|
||||
The `revertReasonTracer` is useful for analyzing failed transactions. If the transaction reverted, the reason for the revert (according to the Solidity contract) is returned. For any other failure, the error message is returned.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
> debug.traceTransaction('0x97695ffb034be7e1faeb372a564bb951ba4ebf4fee4caff2f9d1702497bb2b8b', { tracer: 'revertReasonTracer' })
|
||||
```
|
||||
|
||||
Returns:
|
||||
|
||||
```terminal
|
||||
"execution reverted: tokensMintedPerAddress exceed MAX_TOKENS_MINTED_PER_ADDRESS"
|
||||
```
|
||||
|
||||
### noopTracer
|
||||
### noopTracer {#noop-tracer}
|
||||
|
||||
This tracer is noop. It returns an empty object and is only meant for testing the setup.
|
||||
|
||||
## Javascript tracers
|
||||
## Javascript tracers {#js-tracers}
|
||||
|
||||
There are also a set of tracers written in Javascript. These are less performant than the Go native tracers because of overheads associated with interpreting the Javascript in Geth's Go environment.
|
||||
|
||||
### bigram
|
||||
### bigram {#bigram}
|
||||
|
||||
`bigramTracer` counts the opcode bigrams, i.e. how many times 2 opcodes were executed one after the other.
|
||||
|
||||
|
@ -318,7 +318,7 @@ Returns:
|
|||
|
||||
```
|
||||
|
||||
### evmdis
|
||||
### evmdis {#evmdis}
|
||||
|
||||
`evmdisTracer` returns sufficient information from a trace to perform [evmdis](https://github.com/Arachnid/evmdis)-style disassembly
|
||||
|
||||
|
@ -375,7 +375,7 @@ Returns:
|
|||
...
|
||||
```
|
||||
|
||||
### opcount
|
||||
### opcount {#opcount}
|
||||
|
||||
`opcountTracer` counts the total number of opcodes executed and simply returns the number.
|
||||
|
||||
|
@ -399,7 +399,7 @@ Returns:
|
|||
1384
|
||||
```
|
||||
|
||||
### trigram
|
||||
### trigram {#trigram}
|
||||
|
||||
`trigramTracer` counts the opcode trigrams. Trigrams are the possible combinations of three opcodes this tracer reports how many times each combination is seen during execution.
|
||||
|
||||
|
@ -443,7 +443,7 @@ Returns:
|
|||
}
|
||||
```
|
||||
|
||||
### unigram
|
||||
### unigram {#unigram}
|
||||
|
||||
`unigramTracer` counts the frequency of occurrance of each opcode.
|
||||
|
||||
|
@ -475,7 +475,7 @@ Returns:
|
|||
|
||||
```
|
||||
|
||||
## State overrides
|
||||
## State overrides {#state-overrides}
|
||||
|
||||
It is possible to give temporary state modifications to Geth in order to simulate the effects of `eth_call`. For example, some new byetcode could be deployed to some address _temporarily just for the duration of the execution_ and then a transaction interacting with that address canm be traced. This can be used for scenario testing or determining the outcome of some hypothetical transaction before executing for real.
|
||||
|
||||
|
@ -487,6 +487,6 @@ var tracer = //tracer name
|
|||
debug.traceCall({from: , to: , input: }, 'latest', {stateOverrides: {'0x...': {code: code}}, tracer: tracer})
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page showed how to use the tracers that come bundled with Geth. There are a set written in Go and a set written in Javascript. They are invoked by passing their names when calling an API method.
|
||||
This page showed how to use the tracers that come bundled with Geth. There are a set written in Go and a set written in Javascript. They are invoked by passing their names when calling an API method. State overrides can be used in combination with tracers to examine precisely what the EVM will do in some hypothetical scenarios.
|
||||
|
|
|
@ -5,313 +5,11 @@ description: Introduction to writing custom tracers for Geth
|
|||
|
||||
In addition to the default opcode tracer and the built-in tracers, Geth offers the possibility to write custom code that hook to events in the EVM to process and return the data in a consumable format. Custom tracers can be written either in Javascript or Go. JS tracers are good for quick prototyping and experimentation as well as for less intensive applications. Go tracers are performant but require the tracer to be compiled together with the Geth source code.
|
||||
|
||||
## Custom Javascript tracing
|
||||
|
||||
Transaction traces include the complete status of the EVM at every point during the transaction execution, which can be a very large amount of data. Often, users are only interested in a small subset of that data. Javascript trace filters are available to isolate the useful information. Detailed information about `debug_traceTransaction` and its component parts is available in the [reference documentation](/docs/developers/interacting-with-geth/rpc/ns-debug#debug_tracetransaction).
|
||||
|
||||
### A simple filter
|
||||
|
||||
Filters are Javascript functions that select information from the trace to persist and discard based on some conditions. The following Javascript function returns only the sequence of opcodes executed by the transaction as a comma-separated list. The function could be written directly in the Javascript console, but it is cleaner to write it in a separate re-usable file and load it into the console.
|
||||
|
||||
1. Create a file, `filterTrace_1.js`, with this content:
|
||||
|
||||
```javascript
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'step: function(log,db) {this.retVal.push(log.getPC() + ":" + log.op.toString())},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
2. Run the [JavaScript console](/docs/interface/javascript-console).
|
||||
3. Get the hash of a recent transaction from a node or block explorer.
|
||||
|
||||
4. Run this command to run the script:
|
||||
|
||||
```javascript
|
||||
loadScript('filterTrace_1.js');
|
||||
```
|
||||
|
||||
5. Run the tracer from the script. Be patient, it could take a long time.
|
||||
|
||||
```javascript
|
||||
tracer('<hash of transaction>');
|
||||
```
|
||||
|
||||
The bottom of the output looks similar to:
|
||||
|
||||
```sh
|
||||
"3366:POP", "3367:JUMP", "1355:JUMPDEST", "1356:PUSH1", "1358:MLOAD", "1359:DUP1", "1360:DUP3", "1361:ISZERO", "1362:ISZERO",
|
||||
"1363:ISZERO", "1364:ISZERO", "1365:DUP2", "1366:MSTORE", "1367:PUSH1", "1369:ADD", "1370:SWAP2", "1371:POP", "1372:POP", "1373:PUSH1",
|
||||
"1375:MLOAD", "1376:DUP1", "1377:SWAP2", "1378:SUB", "1379:SWAP1", "1380:RETURN"
|
||||
```
|
||||
|
||||
6. Run this line to get a more readable output with each string in its own line.
|
||||
|
||||
```javascript
|
||||
console.log(JSON.stringify(tracer('<hash of transaction>'), null, 2));
|
||||
```
|
||||
|
||||
More information about the `JSON.stringify` function is available [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
|
||||
|
||||
The commands above worked by calling the same `debug.traceTransaction` function that was previously explained in [basic traces](/docs/dapp/tracing), but with a new parameter, `tracer`. This parameter takes the JavaScript object formated as a string. In the case of the trace above, it is:
|
||||
|
||||
```javascript
|
||||
{
|
||||
retVal: [],
|
||||
step: function(log,db) {this.retVal.push(log.getPC() + ":" + log.op.toString())},
|
||||
fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},
|
||||
result: function(ctx,db) {return this.retVal}
|
||||
}
|
||||
```
|
||||
|
||||
This object has three member functions:
|
||||
|
||||
- `step`, called for each opcode.
|
||||
- `fault`, called if there is a problem in the execution.
|
||||
- `result`, called to produce the results that are returned by `debug.traceTransaction` after the execution is done.
|
||||
|
||||
In this case, `retVal` is used to store the list of strings to return in `result`.
|
||||
|
||||
The `step` function adds to `retVal` the program counter and the name of the opcode there. Then, in `result`, this list is returned to be sent to the caller.
|
||||
|
||||
### Filtering with conditions
|
||||
|
||||
For actual filtered tracing we need an `if` statement to only log relevant information. For example, to isolate the transaction's interaction with storage, the following tracer could be used:
|
||||
|
||||
```javascript
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'step: function(log,db) {' +
|
||||
' if(log.op.toNumber() == 0x54) ' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD");' +
|
||||
' if(log.op.toNumber() == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE");' +
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The `step` function here looks at the opcode number of the op, and only pushes an entry if the opcode is `SLOAD` or `SSTORE` ([here is a list of EVM opcodes and their numbers](https://github.com/wolflo/evm-opcodes)). We could have used `log.op.toString()` instead, but it is faster to compare numbers rather than strings.
|
||||
|
||||
The output looks similar to this:
|
||||
|
||||
```javascript
|
||||
[
|
||||
"5921: SLOAD",
|
||||
.
|
||||
.
|
||||
.
|
||||
"2413: SSTORE",
|
||||
"2420: SLOAD",
|
||||
"2475: SSTORE",
|
||||
"6094: SSTORE"
|
||||
]
|
||||
```
|
||||
|
||||
### Stack Information
|
||||
|
||||
The trace above reports the program counter (PC) and whether the program read from storage or wrote to it. That alone isn't particularly useful. To know more, the `log.stack.peek` function can be used to peek into the stack. `log.stack.peek(0)` is the stack top, `log.stack.peek(1)` the entry below it, etc.
|
||||
|
||||
The values returned by `log.stack.peek` are Go `big.Int` objects. By default they are converted to JavaScript floating point numbers, so you need `toString(16)` to get them as hexadecimals, which is how 256-bit values such as storage cells and their content are normally represented.
|
||||
|
||||
#### Storage Information
|
||||
|
||||
The function below provides a trace of all the storage operations and their parameters. This gives a more complete picture of the program's interaction with storage.
|
||||
|
||||
```javascript
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'step: function(log,db) {' +
|
||||
' if(log.op.toNumber() == 0x54) ' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD " + ' +
|
||||
' log.stack.peek(0).toString(16));' +
|
||||
' if(log.op.toNumber() == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE " +' +
|
||||
' log.stack.peek(0).toString(16) + " <- " +' +
|
||||
' log.stack.peek(1).toString(16));' +
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The output is similar to:
|
||||
|
||||
```javascript
|
||||
[
|
||||
"5921: SLOAD 0",
|
||||
.
|
||||
.
|
||||
.
|
||||
"2413: SSTORE 3f0af0a7a3ed17f5ba6a93e0a2a05e766ed67bf82195d2dd15feead3749a575d <- fb8629ad13d9a12456",
|
||||
"2420: SLOAD cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870",
|
||||
"2475: SSTORE cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870 <- 358c3de691bd19",
|
||||
"6094: SSTORE 0 <- 1"
|
||||
]
|
||||
```
|
||||
|
||||
#### Operation Results
|
||||
|
||||
One piece of information missing from the function above is the result on an `SLOAD` operation. The state we get inside `log` is the state prior to the execution of the opcode, so that value is not known yet. For more operations we can figure it out for ourselves, but we don't have access to the
|
||||
storage, so here we can't.
|
||||
|
||||
The solution is to have a flag, `afterSload`, which is only true in the opcode right after an `SLOAD`, when we can see the result at the top of the stack.
|
||||
|
||||
```javascript
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'afterSload: false,' +
|
||||
'step: function(log,db) {' +
|
||||
' if(this.afterSload) {' +
|
||||
' this.retVal.push(" Result: " + ' +
|
||||
' log.stack.peek(0).toString(16)); ' +
|
||||
' this.afterSload = false; ' +
|
||||
' } ' +
|
||||
' if(log.op.toNumber() == 0x54) {' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD " + ' +
|
||||
' log.stack.peek(0).toString(16));' +
|
||||
' this.afterSload = true; ' +
|
||||
' } ' +
|
||||
' if(log.op.toNumber() == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE " +' +
|
||||
' log.stack.peek(0).toString(16) + " <- " +' +
|
||||
' log.stack.peek(1).toString(16));' +
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The output now contains the result in the line that follows the `SLOAD`.
|
||||
|
||||
```javascript
|
||||
[
|
||||
"5921: SLOAD 0",
|
||||
" Result: 1",
|
||||
.
|
||||
.
|
||||
.
|
||||
"2413: SSTORE 3f0af0a7a3ed17f5ba6a93e0a2a05e766ed67bf82195d2dd15feead3749a575d <- fb8629ad13d9a12456",
|
||||
"2420: SLOAD cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870",
|
||||
" Result: 0",
|
||||
"2475: SSTORE cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870 <- 358c3de691bd19",
|
||||
"6094: SSTORE 0 <- 1"
|
||||
]
|
||||
```
|
||||
|
||||
### Dealing With Calls Between Contracts
|
||||
|
||||
So the storage has been treated as if there are only 2<sup>256</sup> cells. However, that is not true. Contracts can call other contracts, and then the storage involved is the storage of the other contract. We can see the address of the current contract in `log.contract.getAddress()`. This value is the execution context - the contract whose storage we are using - even when code from another contract is executed (by using
|
||||
[`CALLCODE` or `DELEGATECALL`](https://docs.soliditylang.org/en/v0.8.14/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries)).
|
||||
|
||||
However, `log.contract.getAddress()` returns an array of bytes. To convert this to the familiar hexadecimal representation of Ethereum addresses, `this.byteHex()` and `array2Hex()` can be used.
|
||||
|
||||
```javascript
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'afterSload: false,' +
|
||||
'callStack: [],' +
|
||||
'byte2Hex: function(byte) {' +
|
||||
' if (byte < 0x10) ' +
|
||||
' return "0" + byte.toString(16); ' +
|
||||
' return byte.toString(16); ' +
|
||||
'},' +
|
||||
'array2Hex: function(arr) {' +
|
||||
' var retVal = ""; ' +
|
||||
' for (var i=0; i<arr.length; i++) ' +
|
||||
' retVal += this.byte2Hex(arr[i]); ' +
|
||||
' return retVal; ' +
|
||||
'}, ' +
|
||||
'getAddr: function(log) {' +
|
||||
' return this.array2Hex(log.contract.getAddress());' +
|
||||
'}, ' +
|
||||
'step: function(log,db) {' +
|
||||
' var opcode = log.op.toNumber();' +
|
||||
// SLOAD
|
||||
' if (opcode == 0x54) {' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD " + ' +
|
||||
' this.getAddr(log) + ":" + ' +
|
||||
' log.stack.peek(0).toString(16));' +
|
||||
' this.afterSload = true; ' +
|
||||
' } ' +
|
||||
// SLOAD Result
|
||||
' if (this.afterSload) {' +
|
||||
' this.retVal.push(" Result: " + ' +
|
||||
' log.stack.peek(0).toString(16)); ' +
|
||||
' this.afterSload = false; ' +
|
||||
' } ' +
|
||||
// SSTORE
|
||||
' if (opcode == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE " +' +
|
||||
' this.getAddr(log) + ":" + ' +
|
||||
' log.stack.peek(0).toString(16) + " <- " +' +
|
||||
' log.stack.peek(1).toString(16));' +
|
||||
// End of step
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The output is similar to:
|
||||
|
||||
```javascript
|
||||
[
|
||||
"423: SLOAD 22ff293e14f1ec3a09b137e9e06084afd63addf9:360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
" Result: 360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
"10778: SLOAD 22ff293e14f1ec3a09b137e9e06084afd63addf9:6",
|
||||
" Result: 6",
|
||||
.
|
||||
.
|
||||
.
|
||||
"13529: SLOAD f2d68898557ccb2cf4c10c3ef2b034b2a69dad00:8328de571f86baa080836c50543c740196dbc109d42041802573ba9a13efa340",
|
||||
" Result: 8328de571f86baa080836c50543c740196dbc109d42041802573ba9a13efa340",
|
||||
"423: SLOAD f2d68898557ccb2cf4c10c3ef2b034b2a69dad00:360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
" Result: 360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
"13529: SLOAD f2d68898557ccb2cf4c10c3ef2b034b2a69dad00:b38558064d8dd9c883d2a8c80c604667ddb90a324bc70b1bac4e70d90b148ed4",
|
||||
" Result: b38558064d8dd9c883d2a8c80c604667ddb90a324bc70b1bac4e70d90b148ed4",
|
||||
"11041: SSTORE 22ff293e14f1ec3a09b137e9e06084afd63addf9:6 <- 0"
|
||||
]
|
||||
```
|
||||
|
||||
## Other traces
|
||||
|
||||
This tutorial has focused on `debug_traceTransaction()` which reports information about individual transactions. There are also RPC endpoints that provide different information, including tracing the EVM execution within a block, between two blocks, for specific `eth_call`s or rejected blocks. The full list of trace functions can be explored in the [reference documentation](/docs/interacting_with_geth/RPC/ns-debug).
|
||||
|
||||
## Custom Go tracing
|
||||
|
||||
Custom tracers can also be made more performant by writing them in Go. The gain in performance mostly comes from the fact that Geth doesn't need
|
||||
to interpret JS code and can execute native functions. Geth comes with several built-in [native tracers](https://github.com/ethereum/go-ethereum/tree/master/eth/tracers/native) which can serve as examples. Please note that unlike JS tracers, Go tracing scripts cannot be simply passed as an argument to the API. They will need to be added to and compiled with the rest of the Geth source code.
|
||||
Custom tracers can also be made more performant by writing them in Go. The gain in performance mostly comes from the fact that Geth doesn't need to interpret JS code and can execute native functions. Geth comes with several built-in [native tracers](https://github.com/ethereum/go-ethereum/tree/master/eth/tracers/native) which can serve as examples. Please note that unlike JS tracers, Go tracing scripts cannot be simply passed as an argument to the API. They will need to be added to and compiled with the rest of the Geth source code.
|
||||
|
||||
In this section a simple native tracer that counts the number of opcodes will be covered. First follow the instructions to [clone and build](/docs/getting_started/Installing-Geth) Geth from source code. Next save the following snippet as a `.go` file and add it to `eth/tracers/native`:
|
||||
In this section a simple native tracer that counts the number of opcodes will be covered. First follow the instructions to [clone and build](/content/docs/getting_started/Installing-Geth.md) Geth from source code. Next save the following snippet as a `.go` file and add it to `eth/tracers/native`:
|
||||
|
||||
```go
|
||||
package native
|
||||
|
@ -339,7 +37,7 @@ type opcounter struct {
|
|||
reason error // Textual reason for the interruption
|
||||
}
|
||||
|
||||
func newOpcounter(ctx *tracers.Context) tracers.Tracer {
|
||||
func newOpcounter(ctx *tracers.Context, cfg json.RawMessage) tracers.Tracer {
|
||||
return &opcounter{counts: make(map[string]int)}
|
||||
}
|
||||
|
||||
|
@ -397,9 +95,11 @@ func (t *opcounter) Stop(err error) {
|
|||
}
|
||||
```
|
||||
|
||||
Every method of the [EVMLogger interface](https://pkg.go.dev/github.com/ethereum/go-ethereum/core/vm#EVMLogger) needs to be implemented (even if empty). Key parts to notice are the `init()` function which registers the tracer in Geth, the `CaptureState` hook where the opcode counts are incremented and `GetResult` where the result is serialized and delivered. To test this, the source is first compiled with `make geth`. Then in the console it can be invoked through the usual API methods by passing in the name it was registered under:
|
||||
Every method of the [EVMLogger interface](https://pkg.go.dev/github.com/ethereum/go-ethereum/core/vm#EVMLogger) needs to be implemented (even if empty). Key parts to notice are the `init()` function which registers the tracer in Geth, the `CaptureState` hook where the opcode counts are incremented and `GetResult` where the result is serialized and delivered. Note that the constructor takes in a `cfg json.RawMessage`. This will be filled with a JSON object that user provides to the tracer to pass in optional config fields.
|
||||
|
||||
```console
|
||||
To test out this tracer the source is first compiled with `make geth`. Then in the console it can be invoked through the usual API methods by passing in the name it was registered under:
|
||||
|
||||
```sh
|
||||
> debug.traceTransaction('0x7ae446a7897c056023a8104d254237a8d97783a92900a7b0f7db668a9432f384', { tracer: 'opcounter' })
|
||||
{
|
||||
ADD: 4,
|
||||
|
@ -409,6 +109,169 @@ Every method of the [EVMLogger interface](https://pkg.go.dev/github.com/ethereum
|
|||
}
|
||||
```
|
||||
|
||||
## Custom Javascript tracing
|
||||
|
||||
Transaction traces include the complete status of the EVM at every point during the transaction execution, which can be a very large amount of data. Often, users are only interested in a small subset of that data. Javascript trace filters are available to isolate the useful information.
|
||||
|
||||
Specifying the `tracer` option in one of the tracing methods (see list in [reference](/docs/rpc/ns-debug)) enables JavaScript-based tracing. In this mode, `tracer` is interpreted as a JavaScript expression that is expected to evaluate to an object which must expose the `result` and `fault` methods. There exist 4 additional methods, namely: `setup`, `step`, `enter`, and `exit`. `enter` and `exit` must be present or omitted together.
|
||||
|
||||
### Setup
|
||||
|
||||
`setup` is invoked once, in the beginning when the tracer is being constructed by Geth for a given transaction. It takes in one argument `config`. `config` is tracer-specific and allows users to pass in options to the tracer. `config` is to be JSON-decoded for usage and its default value is `"{}"`.
|
||||
|
||||
The `config` in the following example is the `onlyTopCall` option available in the `callTracer`:
|
||||
|
||||
```js
|
||||
debug.traceTransaction('<txhash>, { tracer: 'callTracer', tracerConfig: { onlyTopCall: true } })
|
||||
```
|
||||
|
||||
The config in the following example is the `diffMode` option available in the `prestateTracer`:
|
||||
|
||||
```js
|
||||
debug.traceTransaction('<txhash>, { tracer: 'prestateTracer': tracerConfig: { diffMode: true } })
|
||||
```
|
||||
|
||||
### Step
|
||||
|
||||
`step` is a function that takes two arguments, `log` and `db`, and is called for each step of the EVM, or when an error occurs, as the specified transaction is traced.
|
||||
|
||||
`log` has the following fields:
|
||||
|
||||
- `op`: Object, an OpCode object representing the current opcode
|
||||
- `stack`: Object, a structure representing the EVM execution stack
|
||||
- `memory`: Object, a structure representing the contract's memory space
|
||||
- `contract`: Object, an object representing the account executing the current operation
|
||||
|
||||
and the following methods:
|
||||
|
||||
- `getPC()` - returns a Number with the current program counter
|
||||
- `getGas()` - returns a Number with the amount of gas remaining
|
||||
- `getCost()` - returns the cost of the opcode as a Number
|
||||
- `getDepth()` - returns the execution depth as a Number
|
||||
- `getRefund()` - returns the amount to be refunded as a Number
|
||||
- `getError()` - returns information about the error if one occured, otherwise returns `undefined`
|
||||
|
||||
If error is non-empty, all other fields should be ignored.
|
||||
|
||||
For efficiency, the same `log` object is reused on each execution step, updated with current values; make sure to copy values you want to preserve beyond the current call. For instance, this step function will not work:
|
||||
|
||||
```js
|
||||
function(log) {
|
||||
this.logs.append(log);
|
||||
}
|
||||
```
|
||||
|
||||
But this step function will:
|
||||
|
||||
```js
|
||||
function(log) {
|
||||
this.logs.append({gas: log.getGas(), pc: log.getPC(), ...});
|
||||
}
|
||||
```
|
||||
|
||||
`log.op` has the following methods:
|
||||
|
||||
- `isPush()` - returns true if the opcode is a PUSHn
|
||||
- `toString()` - returns the string representation of the opcode
|
||||
- `toNumber()` - returns the opcode's number
|
||||
|
||||
`log.memory` has the following methods:
|
||||
|
||||
- `slice(start, stop)` - returns the specified segment of memory as a byte slice
|
||||
- `getUint(offset)` - returns the 32 bytes at the given offset
|
||||
- `length()` - returns the memory size
|
||||
|
||||
`log.stack` has the following methods:
|
||||
|
||||
- `peek(idx)` - returns the idx-th element from the top of the stack (0 is the topmost element) as a big.Int
|
||||
- `length()` - returns the number of elements in the stack
|
||||
|
||||
`log.contract` has the following methods:
|
||||
|
||||
- `getCaller()` - returns the address of the caller
|
||||
- `getAddress()` - returns the address of the current contract
|
||||
- `getValue()` - returns the amount of value sent from caller to contract as a big.Int
|
||||
- `getInput()` - returns the input data passed to the contract
|
||||
|
||||
`db` has the following methods:
|
||||
|
||||
- `getBalance(address)` - returns a `big.Int` with the specified account's balance
|
||||
- `getNonce(address)` - returns a Number with the specified account's nonce
|
||||
- `getCode(address)` - returns a byte slice with the code for the specified account
|
||||
- `getState(address, hash)` - returns the state value for the specified account and the specified hash
|
||||
- `exists(address)` - returns true if the specified address exists
|
||||
|
||||
If the step function throws an exception or executes an illegal operation at any point, it will not be called on any further VM steps, and the error will be returned to the caller.
|
||||
|
||||
### Result
|
||||
|
||||
`result` is a function that takes two arguments `ctx` and `db`, and is expected to return a JSON-serializable value to return to the RPC caller.
|
||||
|
||||
`ctx` is the context in which the transaction is executing and has the following fields:
|
||||
|
||||
- `type` - String, one of the two values `CALL` and `CREATE`
|
||||
- `from` - Address, sender of the transaction
|
||||
- `to` - Address, target of the transaction
|
||||
- `input` - Buffer, input transaction data
|
||||
- `gas` - Number, gas budget of the transaction
|
||||
- `gasUsed` - Number, amount of gas used in executing the transaction (excludes txdata costs)
|
||||
- `gasPrice` - Number, gas price configured in the transaction being executed
|
||||
- `intrinsicGas` - Number, intrinsic gas for the transaction being executed
|
||||
- `value` - big.Int, amount to be transferred in wei
|
||||
- `block` - Number, block number
|
||||
- `output` - Buffer, value returned from EVM
|
||||
- `time` - String, execution runtime
|
||||
|
||||
And these fields are only available for tracing mined transactions (i.e. not available when doing `debug_traceCall`):
|
||||
|
||||
- `blockHash` - Buffer, hash of the block that holds the transaction being executed
|
||||
- `txIndex` - Number, index of the transaction being executed in the block
|
||||
- `txHash` - Buffer, hash of the transaction being executed
|
||||
|
||||
### Fault
|
||||
|
||||
`fault` is a function that takes two arguments, `log` and `db`, just like `step` and is invoked when an error happens during the execution of an opcode which wasn't reported in `step`. The method `log.getError()` has information about the error.
|
||||
|
||||
### Enter & Exit
|
||||
|
||||
`enter` and `exit` are respectively invoked on stepping in and out of an internal call. More specifically they are invoked on the `CALL` variants, `CREATE` variants and also for the transfer implied by a `SELFDESTRUCT`.
|
||||
|
||||
`enter` takes a `callFrame` object as argument which has the following methods:
|
||||
|
||||
- `getType()` - returns a string which has the type of the call frame
|
||||
- `getFrom()` - returns the address of the call frame sender
|
||||
- `getTo()` - returns the address of the call frame target
|
||||
- `getInput()` - returns the input as a buffer
|
||||
- `getGas()` - returns a Number which has the amount of gas provided for the frame
|
||||
- `getValue()` - returns a `big.Int` with the amount to be transferred only if available, otherwise `undefined`
|
||||
|
||||
`exit` takes in a `frameResult` object which has the following methods:
|
||||
|
||||
- `getGasUsed()` - returns amount of gas used throughout the frame as a Number
|
||||
- `getOutput()` - returns the output as a buffer
|
||||
` -getError()` - returns an error if one occured during execution and `undefined` otherwise
|
||||
|
||||
### Usage
|
||||
|
||||
Note that several values are Golang big.Int objects, not JavaScript numbers or JS bigints. As such, they have the same interface as described in the godocs. Their default serialization to JSON is as a Javascript number; to serialize large numbers accurately call `.String()` on them. For convenience, `big.NewInt(x)` is provided, and will convert a uint to a Go BigInt.
|
||||
|
||||
Usage example, returns the top element of the stack at each CALL opcode only:
|
||||
|
||||
```js
|
||||
debug.traceTransaction(txhash, {
|
||||
tracer:
|
||||
'{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == "CALL") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}'
|
||||
});
|
||||
```
|
||||
|
||||
## Other traces
|
||||
|
||||
This tutorial has focused on `debug_traceTransaction()` which reports information
|
||||
about individual transactions. There are also RPC endpoints that provide different
|
||||
information, including tracing the EVM execution within a block, between two blocks,
|
||||
for specific `eth_call`s or rejected blocks. The full list of trace functions can
|
||||
be explored in the [reference documentation](/content/docs/interacting_with_geth/RPC/ns-debug.md).
|
||||
|
||||
## Summary
|
||||
|
||||
This page described how to write custom tracers for Geth. Custom tracers can be written in Javascript or Go.
|
||||
|
|
|
@ -3,68 +3,66 @@ title: EVM Tracing
|
|||
description: Introduction to tracing EVM transactions using Geth
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
title: EVM Tracing
|
||||
sort-key: A
|
||||
|
||||
---
|
||||
|
||||
Tracing allows users to examine precisely what was executed by the EVM during some specific transaction or set of transactions. There are two different types of [transactions](https://ethereum.org/en/developers/docs/transactions) in Ethereum: value transfers and contract executions. A value transfer just moves ETH from one account to another. A contract interaction executes some code stored at a contract address which can include altering stored data and transacting multiple times with other contracts and externally-owned accounts. A contract execution transaction can therefore be a complicated web of interactions that can be difficult to unpick. The transaction receipt contains a status code that shows whether the transaction succeeded or failed, but more detailed information is not readily available, meaning it is very difficult to know what a contract execution actually did, what data was modified and which addresses were touched. This is the problem that EVM tracing solves. Geth traces transactions by re-running them locally and collecting data about precisely what was executed by the EVM.
|
||||
|
||||
Also see this [Devcon 2022 talk](https://www.youtube.com/watch?v=b8RdmGsilfU) on tracing in Geth.
|
||||
|
||||
## State availability
|
||||
## State availability {#state-availability}
|
||||
|
||||
In its simplest form, tracing a transaction entails requesting the Ethereum node to reexecute the desired transaction with varying degrees of data collection and have it return an aggregated summary. In order for a Geth node to reexecute a transaction, all historical state accessed by the transaction must be available. This includes:
|
||||
|
||||
- Balance, nonce, bytecode and storage of both the recipient as well as all internally invoked contracts.
|
||||
- Block metadata referenced during execution of both the outer as well as all internally created transactions.
|
||||
- Intermediate state generated by all preceding transactions contained in the same block as the one being traced.
|
||||
- Balance, nonce, bytecode and storage of both the recipient as well as all
|
||||
internally invoked contracts.
|
||||
- Block metadata referenced during execution of both the outer as well as all
|
||||
internally created transactions.
|
||||
- Intermediate state generated by all preceding transactions contained in the
|
||||
same block as the one being traced.
|
||||
|
||||
This means there are limits on the transactions that can be traced imposed by the synchronization and pruning configuration of a node:
|
||||
|
||||
- An **archive** node retains **all historical data** back to genesis. It can therefore trace arbitrary transactions at any point in the history of the chain. Tracing a single transaction requires reexecuting all preceding transactions in the same block.
|
||||
|
||||
- A **node synced from genesis** node only retains the most recent 128 block states in memory. Older states are represented by a sequence of occasional checkpoints that intermediate states can be regenerated from. This means that states within the msot recent 128 blocks are immediately available, older states have to be regenerated from snapshots "on-the-fly". If the distance between the requested transaction and the most recent checkpoint is large, rebuilding the state can take a long time. Tracing a single transaction requires reexecuting all preceding transactions in the same block **and** all preceding blocks until the previous stored snapshot.
|
||||
- A **node synced from genesis** node only retains the most recent 128 block states in memory. Older states are represented by a sequence of occasional checkpoints that intermediate states can be regenerated from. This means that states within the most recent 128 blocks are immediately available, older states have to be regenerated from snapshots "on-the-fly". If the distance between the requested transaction and the most recent checkpoint is large, rebuilding the state can take a long time. Tracing a single transaction requires reexecuting all preceding transactions in the same block **and** all preceding blocks until the previous stored snapshot.
|
||||
|
||||
- A **snap synced** node holds the most recent 128 blocks in memory, so transactions in that range are always accessible. However, snap-sync only starts processing from a relatively recent block (as opposed to genesis for a full node). Between the initial sync block and the 128 most recent blocks, the node stores occasional checkpoints that can be used to rebuild the state on-the-fly. This means transactions can be traced back as far as the block that was used for the initial sync. Tracing a single transaction requires reexecuting all preceding transactions in the same block,
|
||||
**and** all preceding blocks until the previous stored snapshot.
|
||||
- A **snap synced** node holds the most recent 128 blocks in memory, so transactions in that range are always accessible. However, snap-sync only starts processing from a relatively recent block (as opposed to genesis for a full node). Between the initial sync block and the 128 most recent blocks, the node stores occasional checkpoints that can be used to rebuild the state on-the-fly. This means transactions can be traced back as far as the block that was used for the initial sync. Tracing a single transaction requires reexecuting all preceding transactions in the same block, **and** all preceding blocks until the previous stored snapshot.
|
||||
|
||||
- A **light synced** node retrieving data **on demand** can in theory trace transactions for which all required historical state is readily available in the network. This is because the data required to generate the trace is requested from an les-serving full node. In practice, data
|
||||
availability **cannot** be reasonably assumed.
|
||||
- A **light synced** node retrieving data **on demand** can in theory trace transactions for which all required historical state is readily available in the network. This is because the data required to generate the trace is requested from an les-serving full node. In practice, data availability **cannot** be reasonably assumed.
|
||||
|
||||
![state pruning options](/public/images/state-pruning.png)
|
||||
![state pruning options](/public/images/docs/state-pruning.png)
|
||||
|
||||
_This image shows the state stored by each sync-mode - red indicates stored state. The full width of each line represents origin to present head_
|
||||
|
||||
More detailed information about syncing is available on the [sync modes page](/docs/fundamentals/sync-modes).
|
||||
More detailed information about syncing is available on the [sync modes page](/docs/interface/sync-modes).
|
||||
|
||||
When a trace of a specific transaction is executed, the state is prepared by fetching the state of the parent block from the database. If it is not available, Geth will crawl backwards in time to find the next available state but only up to a limit defined in the `reexec` parameter which defaults to 128 blocks. If no state is available within the `reexec` window then the trace fails with `Error: required historical state unavailable` and the `reexec` parameter must be increased. If a valid state _is_ found in the `reexec` window, then Geth sequentially re-executes the transcations in each block between the last available state and the target block. The greater the value of `reexec` the longer the tracing will take because more blocks have to be re-executed to regenerate the target state.
|
||||
|
||||
The `debug_getAccessibleStates` endpoint is a useful tool for estimating a suitable value for `reexec`. Passing the number of the block that contains the target transaction and a search distance to this endpoint will return the number of blocks behind the current head where the most recent available state exists. This value can be passed to the tracer as `re-exec`.
|
||||
|
||||
It is also possible to force Geth to store the state for specific sequences of block by stopping Geth, running again with `--gcmode archive` for some period - this prevents state prunign for blocks that arrive while Geth is running with `--gcmode archive`.
|
||||
It is also possible to force Geth to store the state for specific sequences of block by stopping Geth, running again with `--gcmode archive` for some period - this prevents state pruning for blocks that arrive while Geth is running with `--gcmode archive`.
|
||||
|
||||
_There are exceptions to the above rules when running batch traces of entire blocks or chain segments. Those will be detailed later._
|
||||
|
||||
## Types of trace
|
||||
## Types of trace {#types-of-trace}
|
||||
|
||||
### Built-in tracers
|
||||
### Basic traces {#basic-traces}
|
||||
|
||||
The simplest type of transaction trace that Geth can generate are raw EVM opcode traces. For every EVM instruction the transaction executes, a structured log entry is emitted, containing all contextual metadata deemed useful. This includes the _program counter_, _opcode name_, _opcode cost_, _remaining gas_, _execution depth_ and any _occurred error_. The structured logs can optionally also contain the content of the _execution stack_, _execution memory_ and _contract storage_.
|
||||
|
||||
Read more about Geth's basic traces on the [basic traces page](/docs/evm-tracing/basic-traces).
|
||||
|
||||
### Built-in tracers {#built-in-tracers}
|
||||
|
||||
The tracing API accepts an optional `tracer` parameter that defines how the data returned to the API call should be processed. If this parameter is ommitted the default tracer is used. The default is the struct (or 'opcode') logger. These raw opcode traces are sometimes useful, but the returned data is very low level and can be too extensive and awkward to read for many use-cases. A full opcode trace can easily go into the hundreds of megabytes, making them very resource intensive to get out of the node and process externally. For these reasons, there are a set of non-default built-in tracers that can be named in the API call to return different data from the method. Under the hood, these tracers are Go or Javascript
|
||||
functions that do some specific preprocessing on the trace data before it is returned.
|
||||
|
||||
More information about Geth's built-in tracers is available on the
|
||||
[built-in tracers](/docs/developers/evm-tracing/built-in-tracers)
|
||||
page.
|
||||
More information about Geth's built-in tracers is available on the [built-in tracers](/docs/evm-tracing/builtin-tracers) page.
|
||||
|
||||
### Custom tracers
|
||||
### Custom tracers {#custom-tracers}
|
||||
|
||||
In addition to built-in tracers, it is possible to provide custom code that hooks to events in the EVM to process and return data in a consumable format. Custom tracers can be written either in Javascript or Go. JS tracers are good for quick prototyping and experimentation as well as for less intensive applications. Go tracers are performant but require the tracer to be compiled together with the Geth source code. This means developers only have to gather the data they actually need, and do any processing at the source.
|
||||
|
||||
More information about custom tracers is available on the [custom tracers](/docs/developers/evm-tracing/custom-tracers) page.
|
||||
More information about custom tracers is available on the [custom tracers](/docs/evm-tracing/custom-tracer) page.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page gave an introduction to the concept of tracing and explained issues around state availability. More detailed information on Geth's built-in and custom tracers can be found on their dedicated pages. on their dedicated pages.
|
||||
This page gave an introduction to the concept of tracing and explained issues around state availability. More detailed information on Geth's built-in and custom tracers can be found on their dedicated pages.
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
---
|
||||
title: Tutorial for Javascript tracing
|
||||
description: Javascript tracing tutorial
|
||||
---
|
||||
|
||||
Geth supports tracing via [custom Javascript tracers](/docs/evm-tracing/custom-tracer#custom-javascript-tracing). This document provides a tutorial with examples on how to achieve this.
|
||||
|
||||
### A simple filter
|
||||
|
||||
Filters are Javascript functions that select information from the trace to persist and discard based on some conditions. The following Javascript function returns only the sequence of opcodes executed by the transaction as a comma-separated list. The function could be written directly in the Javascript console, but it is cleaner to write it in a separate re-usable file and load it into the console.
|
||||
|
||||
1. Create a file, `filterTrace_1.js`, with this content:
|
||||
|
||||
```js
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'step: function(log,db) {this.retVal.push(log.getPC() + ":" + log.op.toString())},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
2. Run the [JavaScript console](https://geth.ethereum.org/docs/interface/javascript-console).
|
||||
3. Get the hash of a recent transaction from a node or block explorer.
|
||||
|
||||
4. Run this command to run the script:
|
||||
|
||||
```js
|
||||
loadScript('filterTrace_1.js');
|
||||
```
|
||||
|
||||
5. Run the tracer from the script. Be patient, it could take a long time.
|
||||
|
||||
```js
|
||||
tracer('<hash of transaction>');
|
||||
```
|
||||
|
||||
The bottom of the output looks similar to:
|
||||
|
||||
```sh
|
||||
"3366:POP", "3367:JUMP", "1355:JUMPDEST", "1356:PUSH1", "1358:MLOAD", "1359:DUP1", "1360:DUP3", "1361:ISZERO", "1362:ISZERO",
|
||||
"1363:ISZERO", "1364:ISZERO", "1365:DUP2", "1366:MSTORE", "1367:PUSH1", "1369:ADD", "1370:SWAP2", "1371:POP", "1372:POP", "1373:PUSH1",
|
||||
"1375:MLOAD", "1376:DUP1", "1377:SWAP2", "1378:SUB", "1379:SWAP1", "1380:RETURN"
|
||||
```
|
||||
|
||||
6. Run this line to get a more readable output with each string in its own line.
|
||||
|
||||
```js
|
||||
console.log(JSON.stringify(tracer('<hash of transaction>'), null, 2));
|
||||
```
|
||||
|
||||
More information about the `JSON.stringify` function is available [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
|
||||
|
||||
The commands above worked by calling the same `debug.traceTransaction` function that was previously explained in [basic traces](https://geth.ethereum.org/docs/dapp/tracing), but with a new parameter, `tracer`. This parameter takes the JavaScript object formated as a string. In the case of the trace above, it is:
|
||||
|
||||
```js
|
||||
{
|
||||
retVal: [],
|
||||
step: function(log,db) {this.retVal.push(log.getPC() + ":" + log.op.toString())},
|
||||
fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},
|
||||
result: function(ctx,db) {return this.retVal}
|
||||
}
|
||||
```
|
||||
|
||||
This object has three member functions:
|
||||
|
||||
- `step`, called for each opcode.
|
||||
- `fault`, called if there is a problem in the execution.
|
||||
- `result`, called to produce the results that are returned by `debug.traceTransaction`
|
||||
- after the execution is done.
|
||||
|
||||
In this case, `retVal` is used to store the list of strings to return in `result`.
|
||||
|
||||
The `step` function adds to `retVal` the program counter and the name of the opcode there. Then, in `result`, this list is returned to be sent to the caller.
|
||||
|
||||
### Filtering with conditions
|
||||
|
||||
For actual filtered tracing we need an `if` statement to only log relevant information. For example, to isolate the transaction's interaction with storage, the following tracer could be used:
|
||||
|
||||
```js
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'step: function(log,db) {' +
|
||||
' if(log.op.toNumber() == 0x54) ' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD");' +
|
||||
' if(log.op.toNumber() == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE");' +
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The `step` function here looks at the opcode number of the op, and only pushes an entry if the opcode is `SLOAD` or `SSTORE` ([here is a list of EVM opcodes and their numbers](https://github.com/wolflo/evm-opcodes)). We could have used `log.op.toString()` instead, but it is faster to compare numbers rather than strings.
|
||||
|
||||
The output looks similar to this:
|
||||
|
||||
```js
|
||||
[
|
||||
"5921: SLOAD",
|
||||
.
|
||||
.
|
||||
.
|
||||
"2413: SSTORE",
|
||||
"2420: SLOAD",
|
||||
"2475: SSTORE",
|
||||
"6094: SSTORE"
|
||||
]
|
||||
```
|
||||
|
||||
### Stack Information
|
||||
|
||||
The trace above reports the program counter (PC) and whether the program read from storage or wrote to it. That alone isn't particularly useful. To know more, the `log.stack.peek` function can be used to peek into the stack. `log.stack.peek(0)` is the stack top, `log.stack.peek(1)` the entry below it, etc.
|
||||
|
||||
The values returned by `log.stack.peek` are Go `big.Int` objects. By default they are converted to JavaScript floating point numbers, so you need `toString(16)` to get them as hexadecimals, which is how 256-bit values such as storage cells and their content are normally represented.
|
||||
|
||||
#### Storage Information
|
||||
|
||||
The function below provides a trace of all the storage operations and their parameters. This gives a more complete picture of the program's interaction with storage.
|
||||
|
||||
```js
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'step: function(log,db) {' +
|
||||
' if(log.op.toNumber() == 0x54) ' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD " + ' +
|
||||
' log.stack.peek(0).toString(16));' +
|
||||
' if(log.op.toNumber() == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE " +' +
|
||||
' log.stack.peek(0).toString(16) + " <- " +' +
|
||||
' log.stack.peek(1).toString(16));' +
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The output is similar to:
|
||||
|
||||
```js
|
||||
[
|
||||
"5921: SLOAD 0",
|
||||
.
|
||||
.
|
||||
.
|
||||
"2413: SSTORE 3f0af0a7a3ed17f5ba6a93e0a2a05e766ed67bf82195d2dd15feead3749a575d <- fb8629ad13d9a12456",
|
||||
"2420: SLOAD cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870",
|
||||
"2475: SSTORE cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870 <- 358c3de691bd19",
|
||||
"6094: SSTORE 0 <- 1"
|
||||
]
|
||||
```
|
||||
|
||||
#### Operation Results
|
||||
|
||||
One piece of information missing from the function above is the result on an `SLOAD` operation. The state we get inside `log` is the state prior to the execution of the opcode, so that value is not known yet. For more operations we can figure it out for ourselves, but we don't have access to the
|
||||
storage, so here we can't.
|
||||
|
||||
The solution is to have a flag, `afterSload`, which is only true in the opcode right after an `SLOAD`, when we can see the result at the top of the stack.
|
||||
|
||||
```javascript
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'afterSload: false,' +
|
||||
'step: function(log,db) {' +
|
||||
' if(this.afterSload) {' +
|
||||
' this.retVal.push(" Result: " + ' +
|
||||
' log.stack.peek(0).toString(16)); ' +
|
||||
' this.afterSload = false; ' +
|
||||
' } ' +
|
||||
' if(log.op.toNumber() == 0x54) {' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD " + ' +
|
||||
' log.stack.peek(0).toString(16));' +
|
||||
' this.afterSload = true; ' +
|
||||
' } ' +
|
||||
' if(log.op.toNumber() == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE " +' +
|
||||
' log.stack.peek(0).toString(16) + " <- " +' +
|
||||
' log.stack.peek(1).toString(16));' +
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The output now contains the result in the line that follows the `SLOAD`.
|
||||
|
||||
```javascript
|
||||
[
|
||||
"5921: SLOAD 0",
|
||||
" Result: 1",
|
||||
.
|
||||
.
|
||||
.
|
||||
"2413: SSTORE 3f0af0a7a3ed17f5ba6a93e0a2a05e766ed67bf82195d2dd15feead3749a575d <- fb8629ad13d9a12456",
|
||||
"2420: SLOAD cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870",
|
||||
" Result: 0",
|
||||
"2475: SSTORE cc39b177dd3a7f50d4c09527584048378a692aed24d31d2eabeddb7f3c041870 <- 358c3de691bd19",
|
||||
"6094: SSTORE 0 <- 1"
|
||||
]
|
||||
```
|
||||
|
||||
### Dealing With Calls Between Contracts
|
||||
|
||||
So the storage has been treated as if there are only 2<sup>256</sup> cells. However, that is not true. Contracts can call other contracts, and then the storage involved is the storage of the other contract. We can see the address of the current contract in `log.contract.getAddress()`. This value is the execution context - the contract whose storage we are using - even when code from another contract is executed (by using
|
||||
[`CALLCODE` or `DELEGATECALL`](https://docs.soliditylang.org/en/v0.8.14/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries)).
|
||||
|
||||
However, `log.contract.getAddress()` returns an array of bytes. To convert this to the familiar hexadecimal representation of Ethereum addresses, `this.byteHex()` and `array2Hex()` can be used.
|
||||
|
||||
```js
|
||||
tracer = function (tx) {
|
||||
return debug.traceTransaction(tx, {
|
||||
tracer:
|
||||
'{' +
|
||||
'retVal: [],' +
|
||||
'afterSload: false,' +
|
||||
'callStack: [],' +
|
||||
'byte2Hex: function(byte) {' +
|
||||
' if (byte < 0x10) ' +
|
||||
' return "0" + byte.toString(16); ' +
|
||||
' return byte.toString(16); ' +
|
||||
'},' +
|
||||
'array2Hex: function(arr) {' +
|
||||
' var retVal = ""; ' +
|
||||
' for (var i=0; i<arr.length; i++) ' +
|
||||
' retVal += this.byte2Hex(arr[i]); ' +
|
||||
' return retVal; ' +
|
||||
'}, ' +
|
||||
'getAddr: function(log) {' +
|
||||
' return this.array2Hex(log.contract.getAddress());' +
|
||||
'}, ' +
|
||||
'step: function(log,db) {' +
|
||||
' var opcode = log.op.toNumber();' +
|
||||
// SLOAD
|
||||
' if (opcode == 0x54) {' +
|
||||
' this.retVal.push(log.getPC() + ": SLOAD " + ' +
|
||||
' this.getAddr(log) + ":" + ' +
|
||||
' log.stack.peek(0).toString(16));' +
|
||||
' this.afterSload = true; ' +
|
||||
' } ' +
|
||||
// SLOAD Result
|
||||
' if (this.afterSload) {' +
|
||||
' this.retVal.push(" Result: " + ' +
|
||||
' log.stack.peek(0).toString(16)); ' +
|
||||
' this.afterSload = false; ' +
|
||||
' } ' +
|
||||
// SSTORE
|
||||
' if (opcode == 0x55) ' +
|
||||
' this.retVal.push(log.getPC() + ": SSTORE " +' +
|
||||
' this.getAddr(log) + ":" + ' +
|
||||
' log.stack.peek(0).toString(16) + " <- " +' +
|
||||
' log.stack.peek(1).toString(16));' +
|
||||
// End of step
|
||||
'},' +
|
||||
'fault: function(log,db) {this.retVal.push("FAULT: " + JSON.stringify(log))},' +
|
||||
'result: function(ctx,db) {return this.retVal}' +
|
||||
'}'
|
||||
}); // return debug.traceTransaction ...
|
||||
}; // tracer = function ...
|
||||
```
|
||||
|
||||
The output is similar to:
|
||||
|
||||
```js
|
||||
[
|
||||
"423: SLOAD 22ff293e14f1ec3a09b137e9e06084afd63addf9:360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
" Result: 360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
"10778: SLOAD 22ff293e14f1ec3a09b137e9e06084afd63addf9:6",
|
||||
" Result: 6",
|
||||
.
|
||||
.
|
||||
.
|
||||
"13529: SLOAD f2d68898557ccb2cf4c10c3ef2b034b2a69dad00:8328de571f86baa080836c50543c740196dbc109d42041802573ba9a13efa340",
|
||||
" Result: 8328de571f86baa080836c50543c740196dbc109d42041802573ba9a13efa340",
|
||||
"423: SLOAD f2d68898557ccb2cf4c10c3ef2b034b2a69dad00:360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
" Result: 360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
"13529: SLOAD f2d68898557ccb2cf4c10c3ef2b034b2a69dad00:b38558064d8dd9c883d2a8c80c604667ddb90a324bc70b1bac4e70d90b148ed4",
|
||||
" Result: b38558064d8dd9c883d2a8c80c604667ddb90a324bc70b1bac4e70d90b148ed4",
|
||||
"11041: SSTORE 22ff293e14f1ec3a09b137e9e06084afd63addf9:6 <- 0"
|
||||
]
|
||||
```
|
|
@ -5,7 +5,7 @@ description: Explanation of how code PRs are reviewed
|
|||
|
||||
The only way to get code into Geth is to submit a pull request (PR). Those pull requests need to be reviewed by someone. This document is a guide that explains our expectations around PRs for both authors and reviewers.
|
||||
|
||||
## Terminology
|
||||
## Terminology {#terminology}
|
||||
|
||||
- The **author** of a pull request is the entity who wrote the diff and submitted it to GitHub.
|
||||
|
||||
|
@ -13,7 +13,7 @@ The only way to get code into Geth is to submit a pull request (PR). Those pull
|
|||
- The **reviewer** is the person assigned to review the diff. The reviewer must be a team member.
|
||||
- The **code owner** is the person responsible for the subsystem being modified by the PR.
|
||||
|
||||
## The Process
|
||||
## The Process {#process}
|
||||
|
||||
The first decision to make for any PR is whether it's worth including at all. This decision lies primarily with the code owner, but may be negotiated with team members.
|
||||
|
||||
|
@ -23,11 +23,11 @@ We expect that reviewers check the style and functionality of the PR, providing
|
|||
|
||||
When communicating with authors, be polite and respectful.
|
||||
|
||||
### Code Style
|
||||
### Code Style {#code-style}
|
||||
|
||||
We expect `gofmt`ed code. For contributions of significant size, we expect authors to understand and use the guidelines in [Effective Go](https://golang.org/doc/effective_go.html). Authors should avoid common mistakes explained in the [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) page.
|
||||
|
||||
### Functional Checks
|
||||
### Functional Checks {#functional-checks}
|
||||
|
||||
For PRs that fix an issue, reviewers should try reproduce the issue and verify that the pull request actually fixes it. Authors can help with this by including a unit test that fails without (and passes with) the change.
|
||||
|
||||
|
@ -35,13 +35,13 @@ For PRs adding new features, reviewers should attempt to use the feature and com
|
|||
|
||||
We expect appropriate unit test coverage. Reviewers should verify that new code is covered by unit tests.
|
||||
|
||||
### CI
|
||||
### CI {#ci}
|
||||
|
||||
Code submitted must pass all unit tests and static analysis ("lint") checks. We use Travis CI to test code on Linux, macOS and AppVeyor to test code on Microsoft Windows.
|
||||
|
||||
For failing CI builds, the issue may not be related to the PR itself. Such failures are usually related to flakey tests. These failures can be ignored (authors don't need to fix unrelated issues), but please file a GH issue so the test gets fixed eventually.
|
||||
|
||||
### Commit Messages
|
||||
### Commit Messages {#commit-messages}
|
||||
|
||||
Commit messages on the master branch should follow the rule below. PR authors are not required to use any particular style because the message can be modified at merge time. Enforcing commit message style is the responsibility of the person merging the PR.
|
||||
|
||||
|
@ -59,7 +59,7 @@ Longer explanation of the change in the commit. You can use multiple sentences h
|
|||
issue notices, e.g. "Fixes #42353".
|
||||
```
|
||||
|
||||
### Special Situations And How To Deal With Them
|
||||
### Special Situations And How To Deal With Them {#special-situations}
|
||||
|
||||
Reviewers may find themselves in one of the sitations below. Here's how to deal with them:
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ a bug report or pull request or otherwise contribute to the Geth source code.
|
|||
|
||||
Please see [Contributing](/docs/developers/contributing) for the Geth contribution guidelines.
|
||||
|
||||
## Building and Testing
|
||||
## Building and Testing {#building-and-testing}
|
||||
|
||||
Developers should use a recent version of Go for building and testing. We use the go toolchain for development, which you can get from the [Go downloads page](https://golang.org/doc/install). Geth is a Go module, and uses the [Go modules system](https://github.com/golang/go/wiki/Modules) to manage dependencies. Using `GOPATH` is not required to build go-ethereum.
|
||||
|
||||
### Building Executables
|
||||
### Building Executables {#building-executables}
|
||||
|
||||
Switch to the go-ethereum repository root directory. All code can be built using the go tool, placing the resulting binary in `$GOPATH/bin`.
|
||||
|
||||
|
@ -28,7 +28,7 @@ go install -v ./cmd/geth
|
|||
|
||||
Cross compilation is not recommended, please build Geth for the host architecture.
|
||||
|
||||
### Testing
|
||||
### Testing {#testing}
|
||||
|
||||
Testing a package:
|
||||
|
||||
|
@ -52,7 +52,7 @@ go test -v -bench . -run BenchmarkJoin
|
|||
|
||||
For more information, see the [go test flags](https://golang.org/cmd/go/#hdr-Testing_flags) documentation.
|
||||
|
||||
### Getting Stack Traces
|
||||
### Getting Stack Traces {#getting-stack-traces}
|
||||
|
||||
A stack trace provides a very detailed look into the current state of the geth node. It helps us to debug issues easier as it contains information about what is currently done by the node. Stack traces can be created by running `debug.stacks()` in the Geth console. If the node was started without the console command or with a script in the background, the following command can be used to dump the stack trace into a file.
|
||||
|
||||
|
@ -142,6 +142,6 @@ killall -QUIT geth
|
|||
|
||||
This will dump stack traces for each instance to their respective log file.
|
||||
|
||||
## Where to go next
|
||||
## Where to go next {#where-next}
|
||||
|
||||
Read the remaning pages in the Geth developer section, and get building!
|
||||
|
|
|
@ -14,13 +14,13 @@ It is often convenient for developers to work in an environment where changes to
|
|||
|
||||
This configuration enables developers to experiment with Geth's source code or develop new applications without having to sync to a pre-existing public network. Blocks are only mined when there are pending transactions. Developers can break things on this network without affecting other users. This page will demonstrate how to spin up a local Geth testnet and a simple smart contract will be deployed to it using the Remix online integrated development environment (IDE).
|
||||
|
||||
## Prerequisites
|
||||
## Prerequisites {#prerequisites}
|
||||
|
||||
It is assumed that the user has a working Geth installation (see [installation guide](/docs/install-and-build/installing-geth)).
|
||||
It would also be helpful to have basic knowledge of Geth and the Geth console. See [Getting Started](/docs/getting-started).
|
||||
Some basic knowledge of [Solidity](https://docs.soliditylang.org/) and [smart contract deployment](https://ethereum.org/en/developers/tutorials/deploying-your-first-smart-contract/) would be useful.
|
||||
|
||||
## Start Geth in Dev Mode
|
||||
## Start Geth in Dev Mode {#start-geth-in-dev-mode}
|
||||
|
||||
Starting Geth in developer mode is as simple as providing the `--dev` flag. It is also possible to create a realistic block creation frequency by setting `--dev.period 13` instead of creating blocks only when transactions are pending. There are also additional configuration options required to follow this tutorial.
|
||||
|
||||
|
@ -166,7 +166,7 @@ The transaction details are displayed as follows:
|
|||
|
||||
Now that the user account is funded with ether, a contract can be created ready to deploy to the Geth node.
|
||||
|
||||
## A simple smart contract
|
||||
## A simple smart contract {#simple-smart-contract}
|
||||
|
||||
This tutorial will make use of a classic example smart contract, `Storage.sol`. This contract exposes two public functions, one to add a value to the contract storage and one to view the stored value. The contract, written in Solidity, is provided below:
|
||||
|
||||
|
@ -192,7 +192,7 @@ contract Storage{
|
|||
|
||||
Solidity is a high-level language that makes code executable by the Ethereum virtual machine (EVM) readable to humans. This means that there is an intermediate step between writing code in Solidity and deploying it to Ethereum. This step is called "compilation" and it converts human-readable code into EVM-executable byte-code. This byte-code is then included in a transaction sent from the Geth node during contract deployment. This can all be done directly from the Geth Javascript console; however this tutorial uses an online IDE called Remix to handle the compilation and deployment of the contract to the local Geth node.
|
||||
|
||||
## Compile and deploy using Remix
|
||||
## Compile and deploy using Remix {#compile-and-deploy}
|
||||
|
||||
In a web browser, open <https://remix.ethereum.org>. This opens an online smart contract development environment. On the left-hand side of the screen there is a side-bar menu that toggles between several toolboxes that are displayed in a vertical panel. On the right hand side of the screen there is an editor and a terminal. This layout is similar to the default layout of many other IDEs such as [VSCode](https://code.visualstudio.com/). The contract defined in the previous section, `Storage.sol` is already available in the `Contracts` directory in Remix. It can be opened and reviewed in the editor.
|
||||
|
||||
|
@ -218,7 +218,7 @@ INFO [05-09|12:27:09.681] Successfully sealed new block number=2 seal
|
|||
INFO [05-09|12:27:09.681] 🔨 mined potential block number=2 hash=e927bc..f2c8ed
|
||||
```
|
||||
|
||||
## Interact with contract using Remix
|
||||
## Interact with contract using Remix {#interact-with-contract}
|
||||
|
||||
The contract is now deployed on a local testnet version of the Etheruem blockchain. This means there is a contract address that contains executable bytecode that can be invoked by sending transactions with instructions, also in bytecode, to that address. Again, this can all be achieved by constructing transactions directly in the Geth console or even by making external http requests using tools such as Curl. Here, Remix is used to retrieve the value, then the same action is taken using the Javascript console.
|
||||
|
||||
|
@ -275,7 +275,7 @@ This returns a value that looks like the following:
|
|||
|
||||
The returned value is a left-padded hexadecimal value. For example, the return value `0x000000000000000000000000000000000000000000000000000000000000000038` corresponds to a value of `56` entered as a uint256 to Remix. After converting from hexadecimal string to decimal number the returned value should be equal to that provided to Remix in the previous step.
|
||||
|
||||
## Reusing --datadir
|
||||
## Reusing --datadir {#reusing-datadir}
|
||||
|
||||
This tutorial used an ephemeral blockchain that is completely destroyed and started afresh during each dev-mode session. However, it is also possible to create persistent blockchain and account data that can be reused across multiple sessions. This is done by providing the `--datadir` flag and a directory name when starting Geth in dev-mode.
|
||||
|
||||
|
@ -283,7 +283,7 @@ This tutorial used an ephemeral blockchain that is completely destroyed and star
|
|||
geth --datadir dev-chain --dev --http --http.api web3,eth,net --http.corsdomain "remix.ethereum.org"
|
||||
```
|
||||
|
||||
## Re-using accounts
|
||||
## Re-using accounts {#reusing-accounts}
|
||||
|
||||
Geth will fail to start in dev-mode if keys have been manually created or imported into the keystore in the `--datadir` directory. This is because the account cannot be automatically unlocked. To resolve this issue, the password defined when the account was created can be saved to a text file and its path passed to the `--password` flag on starting Geth, for example if `password.txt` is saved in the top-level `go-ethereum` directory:
|
||||
|
||||
|
@ -295,6 +295,6 @@ geth --datadir dev-chain --dev --http --http.api web3,eth,net --http.corsdomain
|
|||
|
||||
**Note** that this is an edge-case that applies when both the `--datadir` and `--dev` flags are used and a key has been manually created or imported into the keystore.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This tutorial has demonstrated how to spin up a local developer network using Geth. Having started this development network, a simple contract was deployed to the developer network. Then, Remix was connected to the local Geth node and used to deploy and interact with a contract. Remix was used to add a value to the contract storage and then the value was retrieved using Remix and also using the lower level commands in the Javascript console.
|
||||
|
|
|
@ -19,7 +19,7 @@ Vulnerabilies typically take two forms:
|
|||
|
||||
In most cases so far, vulnerabilities in Geth have been of the second type, where the health of the network is a concern, rather than individual node operators. For such issues, Geth reserves the right to silently patch and ship fixes in new releases.
|
||||
|
||||
### Why silent patches
|
||||
### Why silent patches {#why-slient-patches}
|
||||
|
||||
In the case of Ethereum, it takes a lot of time (weeks, months) to get node operators to update even to a scheduled hard fork. If we were to highlight that a release contains important consensus or DoS fixes, there is always a risk of someone trying to beat node operators to the punch, and exploit the vulnerability. Delaying a potential attack sufficiently to make the majority of node operators immune may be worth the temporary loss of transparency.
|
||||
|
||||
|
@ -27,7 +27,7 @@ The primary goal for the Geth team is the health of the Ethereum network as a wh
|
|||
|
||||
At certain times, it's better to remain silent. This practice is also followed by other projects such as [Monero](https://www.getmonero.org/2017/05/17/disclosure-of-a-major-bug-in-cryptonote-based-currencies.html), [ZCash](https://electriccoin.co/blog/zcash-counterfeiting-vulnerability-successfully-remediated/) and [Bitcoin](https://www.coindesk.com/the-latest-bitcoin-bug-was-so-bad-developers-kept-its-full-details-a-secret).
|
||||
|
||||
### Public transparency
|
||||
### Public transparency {#public-transparency}
|
||||
|
||||
As of November 2020, our policy going forward is:
|
||||
|
||||
|
@ -39,7 +39,7 @@ We hope that this provides sufficient balance between transparency versus the ne
|
|||
|
||||
In keeping with this policy, we have taken inspiration from [Solidity bug disclosure](https://solidity.readthedocs.io/en/develop/bugs.html) - see below.
|
||||
|
||||
## Disclosed vulnerabilities
|
||||
## Disclosed vulnerabilities {#disclosed-vulnerabilities}
|
||||
|
||||
There is a JSON-formatted list ([`vulnerabilities.json`](/vulnerabilities.json)) of some of the known security-relevant vulnerabilities concerning Geth.
|
||||
|
||||
|
@ -74,12 +74,12 @@ The JSON file of known vulnerabilities below is a list of objects, one for each
|
|||
- `CVE`
|
||||
- The assigned `CVE` identifier, if available (optional)
|
||||
|
||||
### What about Github security advisories
|
||||
### What about Github security advisories {#github-security-advisories}
|
||||
|
||||
We prefer to not rely on Github as the only/primary publishing protocol for security advisories, but we plan to use the Github-advisory process as a second channel for disseminating vulnerability-information.
|
||||
|
||||
Advisories published via Github can be accessed [here](https://github.com/ethereum/go-ethereum/security/advisories?state=published).
|
||||
|
||||
## Bug Bounties
|
||||
## Bug Bounties {#bug-bounties}
|
||||
|
||||
The Ethereum Foundation run a bug bounty program to reward responsible disclosures of bugs in client software and specs. The details are provided on [ethereum.org](https://ethereum.org/en/bug-bounty/).
|
||||
|
|
|
@ -7,7 +7,7 @@ This document explains how to set up an [EIP 1459](https://eips.ethereum.org/EIP
|
|||
|
||||
DNS-based node lists can serve as a fallback option when connectivity to the discovery DHT is unavailable. In this guide, node lists will be reated by crawling the discovery DHT, then publishing the resulting node sets under chosen DNS names.
|
||||
|
||||
## Installing the devp2p command
|
||||
## Installing the devp2p command {#installing-devp2p}
|
||||
|
||||
`cmd/devp2p` is a developer utility and is not included in the Geth distribution. You can install this command using `go get`:
|
||||
|
||||
|
@ -21,7 +21,7 @@ To create a signing key, the `ethkey` utility is needed.
|
|||
go get github.com/ethereum/go-ethereum/cmd/ethkey
|
||||
```
|
||||
|
||||
## Crawling the v4 DHT
|
||||
## Crawling the v4 DHT {#crawling-v4-dht}
|
||||
|
||||
Our first step is to compile a list of all reachable nodes. The DHT crawler in cmd/devp2p is a batch process which runs for a set amount of time. You should should schedule this command to run at a regular interval. To create a node list, run
|
||||
|
||||
|
@ -35,7 +35,7 @@ add newly-found nodes to the set, and remove nodes which are no longer alive. Th
|
|||
of the node set improves with each run because the number of revalidations is tracked
|
||||
alongside each node in the set.
|
||||
|
||||
## Creating sub-lists through filtering
|
||||
## Creating sub-lists through filtering {#creating-sublists}
|
||||
|
||||
Once `all-nodes.json` has been created and the set contains a sizeable number of nodes,
|
||||
useful sub-sets of nodes can be extracted using the `devp2p nodeset filter` command. This
|
||||
|
@ -63,7 +63,7 @@ The following filter flags are available:
|
|||
- `-min-age <duration>` restricts the result to nodes which have been live for the
|
||||
given duration.
|
||||
|
||||
## Creating DNS trees
|
||||
## Creating DNS trees {#creating-dns-trees}
|
||||
|
||||
To turn a node list into a DNS node tree, the list needs to be signed. To do this, a key pair is required. To create the key file in the correct format, the cmd/ethkey utility should be used. Choose a strong password to encrypt the key on disk!
|
||||
|
||||
|
@ -79,7 +79,7 @@ devp2p dns sign mainnet.nodes.example.org dnskey.json
|
|||
|
||||
The resulting DNS tree metadata is stored in the `mainnet.nodes.example.org/enrtree-info.json` file.
|
||||
|
||||
## Publishing DNS trees
|
||||
## Publishing DNS trees {#publishing-dns-trees}
|
||||
|
||||
Now that the tree is signed, it can be published to a DNS provider. cmd/devp2p currently supports publishing to CloudFlare DNS and Amazon Route53.TXT records can also be exported as a JSON file and published independently.
|
||||
|
||||
|
@ -91,7 +91,7 @@ devp2p dns to-cloudflare mainnet.nodes.example.org
|
|||
|
||||
Note that this command uses the domain name specified during signing. Any existing records below this name will be erased by cmd/devp2p.
|
||||
|
||||
## Using DNS trees with Geth
|
||||
## Using DNS trees with Geth {#using-dns-trees}
|
||||
|
||||
Once a tree is available through a DNS name, Geth can use it with the `--discovery.dns` command line flag. Node trees are referenced using the `enrtree://` URL scheme. The URL of the tree can be found in the `enrtree-info.json` file created by `devp2p dns sign`. Pass the URL as an argument to the flag in order to make use of the published tree.
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ title: Issue Handling Workflow
|
|||
description: Instructions for managing Github issues
|
||||
---
|
||||
|
||||
## Draft proposal
|
||||
## Draft proposal {#draft-proposal}
|
||||
|
||||
- Keep the number of open issues under 820
|
||||
|
||||
|
@ -47,7 +47,7 @@ It's ok to not set a due date for a milestone, but once you release it, close it
|
|||
|
||||
Optionally, use a project board to collect issues of a larger effort that has an end state and overarches multiple releases.
|
||||
|
||||
## Workflow
|
||||
## Workflow {#workflow}
|
||||
|
||||
The Geth core team hold a weekly or bi-weekly triage meeting. Issues are preselected by [labelling them "status:triage" and sorted the oldest ones first](https://github.com/ethereum/go-ethereum/issues?q=is%3Aopen+is%3Aissue+label%3Astatus%3Atriage+sort%3Acreated-asc). This is when the team goes through the new issues and do one of the following
|
||||
|
||||
|
|
|
@ -5,15 +5,15 @@ description: Tutorial on setting up private Ethereum networks
|
|||
|
||||
This guide explains how to set up a private network of multiple Geth nodes. An Ethereum network is private if the nodes are not connected to the main network. In this context private only means reserved or isolated, rather than protected or secure. A fully controlled, private Ethereum network is useful as a backend for core developers working on issues relating to networking/blockchain syncing etc. Private networks are also useful for Dapp developers testing multi-block and multi-user scenarios.
|
||||
|
||||
## Prerequisites
|
||||
## Prerequisites {#prerequisites}
|
||||
|
||||
To follow the tutorial on this page it is necessary to have a working Geth installation (instructions [here](/docs/getting_started/Installing-Geth)). It is also helpful to understand Geth fundamentals (see [Getting Started](/docs/getting_started/getting_started)).
|
||||
|
||||
## Private Networks
|
||||
## Private Networks {#private-networks}
|
||||
|
||||
A private network is composed of multiple Ethereum nodes that can only connect to each other. In order to run multiple nodes locally, each one requires a separate data directory (`--datadir`). The nodes must also know about each other and be able to exchange information, share an initial state and a common consensus algorithm. The remainder of this page will explain how to configure Geth so that these basic requirements are met, enabling a private network to be started.
|
||||
|
||||
### Choosing A Network ID
|
||||
### Choosing A Network ID {#choosing-network-id}
|
||||
|
||||
Ethereum Mainnet has Network ID = 1. There are also many other networks that Geth can connect to by providing alternative Chain IDs, some are testnets and others are alternative networks built from forks of the Geth source code. Providing a network ID that is not already being used by an existing network or testnet means the nodes using that network ID can only connect to each other, creating a private network. A list of current network IDs is available at [Chainlist.org](https://chainlist.org/). The network ID is controlled using the `networkid` flag, e.g.
|
||||
|
||||
|
@ -21,19 +21,19 @@ Ethereum Mainnet has Network ID = 1. There are also many other networks that Get
|
|||
geth --networkid 12345
|
||||
```
|
||||
|
||||
### Choosing A Consensus Algorithm
|
||||
### Choosing A Consensus Algorithm {#choosing-a-consensus-mechanism}
|
||||
|
||||
While the main network uses proof-of-work (PoW) to secure the blockchain, Geth also supports the the 'Clique' proof-of-authority (PoA) consensus algorithm as an alternative for private networks. Clique is strongly recommended for private testnets because PoA is far less resource-intensive than PoW. The key differences between the consensus algorithms available in Geth are:
|
||||
While the main network uses proof-of-stake (PoS) to secure the blockchain, Geth also supports the the 'Clique' proof-of-authority (PoA) consensus algorithm and the Ethash proof-of-work algorithm as alternatives for private networks. Clique is strongly recommended for private testnets because PoA is far less resource-intensive than PoW. The key differences between the consensus algorithms available in Geth are:
|
||||
|
||||
#### Ethash
|
||||
#### Ethash {#ethash}
|
||||
|
||||
Geth's PoW algorithm, [Ethash](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/mining-algorithms/ethash), is a system that allows open participation by anyone willing to dedicate resources to mining. While this is a critical property for a public network, the overall security of the blockchain strictly depends on the total amount of resources used to secure it. As such, PoW is a poor choice for private networks with few miners. The Ethash mining 'difficulty' is adjusted automatically so that new blocks are created approximately 12 seconds apart. As more mining resources are deployed on the network, creating a new block becomes harder so that the average block time matches the target block time.
|
||||
|
||||
#### Clique
|
||||
#### Clique {#clique}
|
||||
|
||||
Clique consensus is a PoA system where new blocks can be created by authorized 'signers' only. The clique consenus protocol is specified in [EIP-225](https://eips.ethereum.org/EIPS/eip-225). The initial set of authorized signers is configured in the genesis block. Signers can be authorized and de-authorized using a voting mechanism, thus allowing the set of signers to change while the blockchain operates. Clique can be configured to target any block time (within reasonable limits) since it isn't tied to the difficulty adjustment.
|
||||
|
||||
### Creating The Genesis Block
|
||||
### Creating The Genesis Block {#creating-genesis-block}
|
||||
|
||||
Every blockchain starts with a genesis block. When Geth is run with default settings for the first time, it commits the Mainnet genesis to the database. For a private network, it is generally preferable to use a different genesis block. The genesis block is configured using a _genesis.json_ file whose path must be provided to Geth on start-up. When creating a genesis block, a few initial parameters for the private blockchain must be defined:
|
||||
|
||||
|
@ -43,7 +43,7 @@ Every blockchain starts with a genesis block. When Geth is run with default sett
|
|||
|
||||
- Initial allocation of ether (`alloc`). This determines how much ether is available to the addresses listed in the genesis block. Additional ether can be created through mining as the chain progresses.
|
||||
|
||||
#### Clique Example
|
||||
#### Clique Example {#clique-example}
|
||||
|
||||
Below is an example of a `genesis.json` file for a PoA network. The `config` section ensures that all known protocol changes are available and configures the 'clique' engine to be used for consensus. Note that the initial signer set must be configured through the `extradata` field. This field is required for Clique to work.
|
||||
|
||||
|
@ -85,7 +85,7 @@ The `period` configuration option sets the target block time of the chain.
|
|||
}
|
||||
```
|
||||
|
||||
#### Ethash Example
|
||||
#### Ethash Example {#ethash-example}
|
||||
|
||||
Since Ethash is the default consensus algorithm, no additional parameters need to be configured in order to use it. The initial mining difficulty is influenced using the `difficulty` parameter, but note that the difficulty adjustment algorithm will quickly adapt to the amount of mining resources deployed on the chain.
|
||||
|
||||
|
@ -113,7 +113,7 @@ Since Ethash is the default consensus algorithm, no additional parameters need t
|
|||
}
|
||||
```
|
||||
|
||||
### Initializing the Geth Database
|
||||
### Initializing the Geth Database {#initializing-geth-database}
|
||||
|
||||
To create a blockchain node that uses this genesis block, first use `geth init` to import and sets the canonical genesis block for the new chain. This requires the path to `genesis.json` to be passed as an argument.
|
||||
|
||||
|
@ -127,7 +127,7 @@ When Geth is started using `--datadir data` the genesis block defined in `genesi
|
|||
geth --datadir data --networkid 12345
|
||||
```
|
||||
|
||||
### Scheduling Hard Forks
|
||||
### Scheduling Hard Forks {#scheduling-hard-forks}
|
||||
|
||||
As Ethereum protocol development progresses, new features become available. To enable these features on an existing private network, a hard fork must be scheduled. To do this, a future block number must be chosen which determines precisely when the hard fork will activate. Continuing the `genesis.json` example above and assuming the current block number is 35421, a hard fork might be scheduled for block 40000. This hard fork might upgrade the network to conform to the 'London' specs. First, all the Geth instances on the private network must be recent enough to support the specific hard fork. If so, `genesis.json` can be updated so that the `londonBlock` key gets the value 40000. The Geth instances are then shut down and `geth init` is run to update their configuration. When the nodes are restarted they will pick up where they left off and run normally until block 40000, at which point they will automatically upgrade.
|
||||
|
||||
|
@ -147,7 +147,7 @@ The upgrade command is:
|
|||
geth init --datadir data genesis.json
|
||||
```
|
||||
|
||||
### Setting Up Networking
|
||||
### Setting Up Networking {#setting-up-networking}
|
||||
|
||||
With the node configured and initialized, the next step is to set up a peer-to-peer network. This requires a bootstrap node. The bootstrap node is a normal node that is designated to be the entry point that other nodes use to join the network. Any node can be chosen to be the bootstrap node.
|
||||
|
||||
|
@ -180,7 +180,7 @@ geth <other-flags> --netrestrict 172.16.254.0/24
|
|||
|
||||
With the above setting, Geth will only allow connections from the 172.16.254.0/24 subnet, and will not attempt to connect to other nodes outside of the set IP range.
|
||||
|
||||
### Running Member Nodes
|
||||
### Running Member Nodes {#running-member-nodes}
|
||||
|
||||
Before running a member node, it must be initialized with the same genesis file as used for the bootstrap node. With the bootnode operational and externally reachable (`telnet <ip> <port>` will confirm that it is indeed reachable), more Geth nodes can be started and connected to them via the bootstrap node using the `--bootnodes` flag. The process is to start Geth on the same machine as the bootnode, with a separate data directory and listening port and the bootnode node record provided as an argument:
|
||||
|
||||
|
@ -196,7 +196,7 @@ With the member node running, it is possible to check that it is connected to th
|
|||
geth attach data2/geth.ipc --exec admin.peers
|
||||
```
|
||||
|
||||
### Running A Signer (Clique)
|
||||
### Running A Signer (Clique) {#running-a-signer}
|
||||
|
||||
To set up Geth for signing blocks in Clique, a signer account must be available. The account must already be available as a keyfile in the keystore. To use it for signing blocks, it must be unlocked. The following command, for address `0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82` will prompt for the account password, then start signing blocks:
|
||||
|
||||
|
@ -206,7 +206,7 @@ geth <other-flags> --unlock 0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82 --mine
|
|||
|
||||
Mining can be further configured by changing the default gas limit blocks converge to (with `--miner.gastarget`) and the price transactions are accepted at (with `--miner.gasprice`).
|
||||
|
||||
### Running A Miner (Ethash)
|
||||
### Running A Miner (Ethash) {#running-a-miner}
|
||||
|
||||
For PoW in a simple private network, a single CPU miner instance is enough to create a stable stream of blocks at regular intervals. To start a Geth instance for mining, it can be run with all the usual flags plus the following to configure mining:
|
||||
|
||||
|
@ -454,6 +454,6 @@ eth.getBalance('0xc94d95a5106270775351eecfe43f97e8e75e59e8');
|
|||
|
||||
The same steps can then be repeated to attach a console to Node 2.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page explored the various options for configuring a local private network. A step by step guide showed how to set up and launch a private network, unlock the associated accounts, attach a console to check the network status and make some basic interactions.
|
||||
|
|
|
@ -7,10 +7,10 @@ Welcome to the Geth Developer docs!
|
|||
|
||||
This section includes information for builders. If you are building decentralized apps on top of Geth, head to the `dapp-developer` docs. If you are developing Geth itself, explore the `geth-developer` docs.
|
||||
|
||||
## Dapp developers
|
||||
## Dapp developers {#dapp-developers}
|
||||
|
||||
Geth has many features that support dapp developers. There are many built-in tracers implemented in Go or Javascript that allow developers to monitor what is happening in Geth from inside an app, and users can build their own custom tracers too. Geth also includes a suite of tools for interacting with Ethereum smart contracts using Geth functions using Go functions inside Go native applications. There is also information for Geth mobile developers.
|
||||
|
||||
## Geth developers
|
||||
## Geth developers {#geth-developers}
|
||||
|
||||
Geth developers add/remove features and fix bugs in Geth. The `geth-developer` section includes contribution guidelines and documentation relating to testing and disclosing vulnerabilities that willhep you get started with working on Geth.
|
||||
|
|
30
docs/faq.md
30
docs/faq.md
|
@ -3,7 +3,7 @@ title: FAQ
|
|||
description: Frequently asked questions related to Geth
|
||||
---
|
||||
|
||||
### Where can I get more information?
|
||||
### Where can I get more information? {#where-can-i-get-more-information}
|
||||
|
||||
This page contains answers to common questions about Geth. Source code and README documentation can be found on the Geth [Github](https://github.com/ethereum/go-ethereum). You can also ask questions on Geth's [Discord channel](https://discord.gg/WHNkYDsAKU) or keep up to date with Geth on [Twitter](https://twitter.com/go_ethereum). Information about Ethereum in general can be found at [ethereum.org](https://ethereum.org).
|
||||
|
||||
|
@ -13,16 +13,16 @@ The Geth team have also recently started to run AMA's on Reddit:
|
|||
|
||||
It is also recommended to search for 'Geth' and 'go-ethereum' on [ethereum.stackexchange](ethereum.stackexchange.com).
|
||||
|
||||
## What are RPC and IPC?
|
||||
## What are RPC and IPC? {#what-are-rpc-and-ipc}
|
||||
|
||||
IPC stands for Inter-Process Communications. Geth creates a `geth.ipc` file on startup that other processes on the same computer can use to communicate with Geth.
|
||||
RPC stands for Remote Procedure Call. RPC is a mode of communication between processes that may be running on different machines. Geth accepts RPC traffic over HTTP or Websockets. Geth functions are invoked by sending requests that are formatted according to the RPC-API to the node via either IPC or RPC.
|
||||
|
||||
## What is `jwtsecret`?
|
||||
## What is `jwtsecret`? {#what-is-jwtsecret}
|
||||
|
||||
The `jwtsecret` file is required to create an authenticated connection between Geth and a consensus client. JWT stands for JSON Web Token - it is signed using a secret key. The signed token acts as a shared secret used to check that information is sent to and received from the correct peer. Read about how to create `jwt-secret` in Geth on our [Connecting to consensus clients](/docs/getting_started/consensus-clients) page.
|
||||
|
||||
## I noticed my peercount slowly decreasing, and now it is at 0. Restarting doesn't get any peers.
|
||||
## I noticed my peercount slowly decreasing, and now it is at 0. Restarting doesn't get any peers. {#where-are-my-peers}
|
||||
|
||||
This may be because your clock has fallen out of sync with other nodes. You can [force a clock update using ntp](https://askubuntu.com/questions/254826/how-to-force-a-clock-update-using-ntp) like so:
|
||||
|
||||
|
@ -30,11 +30,11 @@ This may be because your clock has fallen out of sync with other nodes. You can
|
|||
sudo ntpdate -s time.nist.gov
|
||||
```
|
||||
|
||||
## I would like to run multiple Geth instances but got the error "Fatal: blockchain db err: resource temporarily unavailable".
|
||||
## I would like to run multiple Geth instances but got the error "Fatal: blockchain db err: resource temporarily unavailable". {#multiple-geth-instances}
|
||||
|
||||
Geth uses a datadir to store the blockchain, accounts and some additional information. This directory cannot be shared between running instances. If you would like to run multiple instances follow [these](/docs/developers/geth-developer/Private-Network) instructions.
|
||||
|
||||
## When I try to use the --password command line flag, I get the error "Could not decrypt key with given passphrase" but the password is correct. Why does this error appear?
|
||||
## When I try to use the --password command line flag, I get the error "Could not decrypt key with given passphrase" but the password is correct. Why does this error appear? {#could-not-decrypt-key}
|
||||
|
||||
Especially if the password file was created on Windows, it may have a Byte Order Mark or other special encoding that the go-ethereum client doesn't currently recognize. You can change this behavior with a PowerShell command like:
|
||||
|
||||
|
@ -44,7 +44,7 @@ echo "mypasswordhere" | out-file test.txt -encoding ASCII
|
|||
|
||||
Additional details and/or any updates on more robust handling are at <https://github.com/ethereum/go-ethereum/issues/19905>.
|
||||
|
||||
## How does Ethereum syncing work?
|
||||
## How does Ethereum syncing work? {#how-does-syncing-work}
|
||||
|
||||
The current default syncing mode used by Geth is called [snap sync](https://github.com/ethereum/devp2p/blob/master/caps/snap.md). Instead of starting from the genesis block and processing all the transactions that ever occurred (which could take weeks), snap sync downloads the blocks, and only verifies the associated proof-of-works, assuming state transitions to be correct. Downloading all the blocks is a straightforward and fast procedure and will relatively quickly reassemble the entire chain.
|
||||
|
||||
|
@ -52,7 +52,7 @@ Many people assume that because they have the blocks, they are in sync. Unfortun
|
|||
|
||||
Geth can also be synced with `--syncmode full`. In this case, Geth downloads and independently verifies every block since genesis in sequence, including re-executing transactions to verify state transitions. Although Geth verifies every block since genesis, the state of 128 blocks only are stored in memory.
|
||||
|
||||
## What's the state trie?
|
||||
## What's the state trie? {#what-is-the-state-trie}
|
||||
|
||||
In the Ethereum mainnet, there are a ton of accounts already, which track the balance, nonce, etc of each user/contract. The accounts themselves are however insufficient to run a node, they need to be cryptographically linked to each block so that nodes can actually verify that the accounts are not tampered with.
|
||||
|
||||
|
@ -60,27 +60,27 @@ This cryptographic linking is done by creating a tree-like data structure, where
|
|||
|
||||
Read more about Merkle Tries in general and the Ethereum state trie specifically on [ethereum.org](https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie)
|
||||
|
||||
## Why does the state trie download phase require a special syncing mode?
|
||||
## Why does the state trie download phase require a special syncing mode? {#state-trie-downloading}
|
||||
|
||||
The trie data structure is an intricate interlink of hundreds of millions of tiny cryptographic proofs (trie nodes). To truly have a synchronized node, you need to download all the account data, as well as all the tiny cryptographic proofs to verify that no one in the network is trying to cheat you. This itself is already a crazy number of data items.
|
||||
|
||||
The part where it gets even messier is that this data is constantly morphing: at every block (roughly 13s), about 1000 nodes are deleted from this trie and about 2000 new ones are added. This means your node needs to synchronize a dataset that is changing more than 200 times per second. Until you actually do gather all the data, your local node is not usable since it cannot cryptographically prove anything about any accounts. But while you're syncing the network is moving forward and most nodes on the network keep the state for only a limited number of recent blocks. Any sync algorithm needs to consider this fact.
|
||||
|
||||
## What happened to fast sync?
|
||||
## What happened to fast sync? {#fast-sync}
|
||||
|
||||
Snap syncing was introduced by version [1.10.0](https://blog.ethereum.org/2021/03/03/geth-v1-10-0/) and was adopted as the default mode in version [1.10.4](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.4). Before that, the default was the "fast" syncing mode, which was dropped in version [1.10.14](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.14). Even though support for fast sync was dropped, Geth still serves the relevant `eth` requests to other client implementations still relying on it. The reason being that snap sync relies on an alternative data structure called the [snapshot](https://blog.ethereum.org/2020/07/17/ask-about-geth-snapshot-acceleration/) which not all clients implement.
|
||||
|
||||
You can read more in the article posted above why snap sync replaced fast sync in Geth.
|
||||
|
||||
## What is wrong with my light client?
|
||||
## What is wrong with my light client? {#light-client}
|
||||
|
||||
Light sync relies on full nodes that serve data to light clients. Historically, this has been hampered by the fact that serving light clients was turned off by default in geth full nodes and few nodes chose to turn it on. Therefore, light nodes often struggled to find peers. Since Ethereum switched to proof-of-stake, Geth light clients have stopped working altogether. Light clients for proof-of-stake Ethereum are expected to be implemented soon!
|
||||
|
||||
## Why do I need another client in addition to Geth?
|
||||
## Why do I need another client in addition to Geth? {#consensus-client}
|
||||
|
||||
Historically, running Geth was enough to turn a computer into an Ethereum node. However, when Ethereum transitioned to proof-of-stake, responsibility for consensus logic and block gossip was handed over to a separate consensus layer client. However, Geth still handles transactions and state management. When the consensus client is required to create a new block, it requests Geth to gather transactions from the transaction pool, execute them to compute a state transition and pass this information back to the consensus client. When the consensus client receives a new block from a peer, it passes the transactions to Geth to re-execute to verify the proposed state-transition. There is a clear separationm of concerns between the two clients, meaning that both are required for a computer function as an Ethereum node.
|
||||
|
||||
## What is staking and how do I participate?
|
||||
## What is staking and how do I participate? {#what-is-staking}
|
||||
|
||||
Staking is how node operators participate in proof-of-stake based consensus. Staking requires validators to deposit 32 ETH to a smart contract and run validator software connected to their node. The validator software broadcasts a vote ("attestation") in favour of checkpoint blocks that it determines to be in the canonical blockchain. The corrct chain is then the one with the greatest accumulation of votes, weighted by the validators stake (up to a maximum of 32 ETH). Geth, as an execution client, does not directly handle consensus logic but it does provide the node with the execution and state-management tools required to validate incoming blocks. Validators are also occasionally picked to propose the next block broadcast across the network. In this case Geth's role is to bundle transactions it has received over the execution layer gossip network, pass them to the consensus client to be included in the block and execute them to determine the resulting state change.
|
||||
|
||||
|
@ -88,10 +88,10 @@ It is entirely possible to run a node without staking any ETH. In this case the
|
|||
|
||||
For step-by-step instruction for staking and spinning up a validating node, see [ethereum.org](https://ethereum.org/en/staking/) or get started on the Ethereum Foundation's [Staking Launchpad](https://launchpad.ethereum.org/).
|
||||
|
||||
## How do I set up a consensus client/validator and connect it to Geth?
|
||||
## How do I set up a consensus client/validator and connect it to Geth? {#how-to-set-up-consensus-client}
|
||||
|
||||
These docs mainly cover how to set up Geth, but since the switch to proof-of-stake it is also necessary to run a consensus client in order to track the head of the chain, and a validator in order to participate in proof-of-stake consensus. A validator node is also required to deposit 32 ETH into a specific smart contract. Our [consensus clients page](/docs/getting-started/consensus-clients) includes a general overview of how to connect a consensus client to Geth. For step by step instructions for specific clients, see their documentation and also see these helpful [online guides](https://github.com/SomerEsat/ethereum-staking-guides).
|
||||
|
||||
## How do I update Geth?
|
||||
## How do I update Geth? {#how-to-update-geth}
|
||||
|
||||
Updating Geth to the latest version simply requires stopping the node, downloading the latest release and restarting the node. Precisely how to download the latest software depends on the installation method - please refer to our [Installation pages](/docs/install-and-build/Installing-Geth).
|
||||
|
|
|
@ -3,9 +3,9 @@ title: Account Management with Clef
|
|||
description: Guide to basic account management using Geth's built-in tools
|
||||
---
|
||||
|
||||
Geth uses an external signer called [Clef](/docs/clef/introduction) to manage accounts. This is a standalone pieve of software that runs independently of, but connects to, a Geth instance. Clef handles account creation, key management and signing transactions/data. This page explains how to use Clef to create and manage accounts for use with Geth. More information about Clef, including advanced setup options, are available in our dedicated Clef docs.
|
||||
Geth uses an external signer called [Clef](/docs/clef/introduction) to manage accounts. This is a standalone piece of software that runs independently of - but connects to - a Geth instance. Clef handles account creation, key management and signing transactions/data. This page explains how to use Clef to create and manage accounts for use with Geth. More information about Clef, including advanced setup options, are available in our dedicated Clef docs.
|
||||
|
||||
## Initialize Clef
|
||||
## Initialize Clef {#initializing-clef}
|
||||
|
||||
The first time Clef is used it needs to be initialized with a master seed that unlocks Clef's secure vault and a path where the vault should be located. Clef will use the vault to store passwords for keystores, javascript auto-signing rules and hashes of rule files. To initialize Clef, pass a vault path to `clef init`, for example to store it in a new directory inside `/home/user/go-ethereum`:
|
||||
|
||||
|
@ -15,7 +15,7 @@ clef init /home/user/go-ethereum/clefdata
|
|||
|
||||
It is extremely important to remember the master seed and keep it secure. It allows access to the accounts under Clef's management.
|
||||
|
||||
## Connecting Geth and Clef
|
||||
## Connecting Geth and Clef {#connecting-geth-and-clef}
|
||||
|
||||
Clef and Geth should be started separately but with complementary configurations so that they can communicate. This requires Clef to know the `chain_id` of the network Geth will connect to so that this information can be included in any signatures. Clef also needs to know the location of the keystore where accounts are (or will be) stored. This is usually in a subdirectory inside Geth's data directory. Clef is also given a data directory which is also often placed conveniently inside Geth's data directory. To enable communication with Clef using Curl, `--http` can be passed which will start an HTTP server on `localhost:8550` by default. To start Clef configured for a Geth node connecting to the Sepolia testnet:
|
||||
|
||||
|
@ -50,11 +50,11 @@ geth --sepolia --datadir sepolia <other flags> --signer=sepolia-data/clef/clef.i
|
|||
|
||||
Remember that it is also necessary to have a consensus client running too, which requires `--http` and several `authrpc` values to be provided to Geth. A complete set of startup commands for the Geth-Lodestar client combinaton plus Clef is provided as an example in this [Gist](https://gist.github.com/jmcook1186/ea5de9215ecedb1b0105bcfa9c30d44c) - adapt it for different client combinations and configurations.
|
||||
|
||||
## Interacting with Clef
|
||||
## Interacting with Clef {#interacting-with-clef}
|
||||
|
||||
There are two modes of interaction with Clef. One is direct interaction, which is achieved by passing requests by HTTP or IPC with JSON-RPC data as defined in Clef's external API. This is the way to do things in Clef that don't require Geth, such as creating and listing accounts, or signing data offline. The other way is via Geth. With Geth started with Clef as an external signer, requests made to Geth that touch account data will route via Clef for approval. By default, the user approves or denies interactions manually by typing `y` or `n` into the Clef console when prompted, but custom rules can also be created to automate common tasks.
|
||||
|
||||
### Creating accounts
|
||||
### Creating accounts {#creating-accounts}
|
||||
|
||||
New accounts can be created using Clef's `account new` method. This generates a new key pair and adds them to the given `keystore` directory:
|
||||
|
||||
|
@ -104,11 +104,11 @@ access to the key and all associated funds!
|
|||
Make sure to backup keystore and passwords in a safe location.
|
||||
```
|
||||
|
||||
### Listing accounts
|
||||
### Listing accounts {#listing-accounts}
|
||||
|
||||
The accounts in the keystore can be listed to the terminal using a simple CLI command as follows:
|
||||
|
||||
```
|
||||
```sh
|
||||
clef list-accounts --keystore <path-to-keystore>
|
||||
```
|
||||
|
||||
|
@ -130,7 +130,7 @@ Accounts can also be listed in the Javascript console using `eth.accounts`, whic
|
|||
|
||||
As well as individual account, any wallets managed by Clef can be listed (which will also print the wallet status and the address and URl of any accounts they contain. This uses the `list-wallets` CLI command.
|
||||
|
||||
```
|
||||
```sh
|
||||
clef list-wallets --keystore <path-to-keystore>
|
||||
```
|
||||
|
||||
|
@ -143,7 +143,7 @@ which returns:
|
|||
- Account 0: 0x8Ef15919F852A8034688a71d8b57Ab0187364009 (keystore:///home/user/go-ethereum/testdata/keystore/UTC--2022-11-01T17-05-11.100536003Z--8ef15919f852a8034688a71d8b57ab0187364009)
|
||||
```
|
||||
|
||||
### Import a keyfile
|
||||
### Import a keyfile {#importing-a-keyfile}
|
||||
|
||||
It is also possible to create an account by importing an existing private key. For example, a user might already have some ether at an address they created using a browser wallet and now wish to use a new Geth node to interact with their funds. In this case, the private key can be exported from the browser wallet and imported into Geth. It is possible to do this using Clef, but currently the method is not externally exposed and requires implementing a UI. There is a Python UI on the Geth Github that could be used as an example or it can be done using the default console UI. However, for now the most straightforward way to import an accoutn from a private key is to use Geth's `account import`.
|
||||
|
||||
|
@ -178,7 +178,7 @@ cat > /path/to/password
|
|||
<type password here>
|
||||
```
|
||||
|
||||
### Import a presale wallet
|
||||
### Import a presale wallet {#import-presale-wallet}
|
||||
|
||||
Assuming the password is known, importing a presale wallet is very easy. Geth's `wallet import` commands are used, passing the path to the wallet.
|
||||
|
||||
|
@ -186,7 +186,7 @@ Assuming the password is known, importing a presale wallet is very easy. Geth's
|
|||
geth wallet import /path/presale.wallet
|
||||
```
|
||||
|
||||
## Updating accounts
|
||||
## Updating accounts {#updating-accounts}
|
||||
|
||||
Clef can be used to set and remove passwords for an existing keystore file. To set a new password, pass the account address to `setpw`:
|
||||
|
||||
|
@ -210,11 +210,11 @@ geth account update a94f5374fce5edbc8e2a8697c15331677e6ebf0b --password path/pas
|
|||
|
||||
Updating the account using `geth account update` replaces the original file with a new one - this means the original file is no longer available after it has been updated. This can be used to update a key file to the latest format.
|
||||
|
||||
## Unlocking accounts
|
||||
## Unlocking accounts {#unlocking-accounts}
|
||||
|
||||
With Clef, indiscriminate account unlocking is no longer a feature. Instead, Clef unlocks are locked until actions are explicitly approved manually by a user, unless they conform to some specific scenario that has been encoded in a ruleset. Please refer to our Clef docs for instructions for how to create rulesets.
|
||||
|
||||
### Transactions
|
||||
### Transactions {#transactions}
|
||||
|
||||
Transactions can be sent using raw JSON requests to Geth or using `web3js` in the Javascript console. Either way, with Clef acting as the signer the transactions will not get sent until approval is given in Clef. The following code snippet shows how a transaction could be sent between two accounts in the keystore using the Javascript console.
|
||||
|
||||
|
@ -225,6 +225,6 @@ var tx = {from: eth.accounts[1], to: eth.accounts[2], value: web3.toWei(5, "ethe
|
|||
eth.sendTransaction(tx)
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page has demonstrated how to manage accounts using Clef and Geth's account management tools. Accounts are stored encrypted by a password. It is critical that the account passwords and the keystore directory are safely and securely backed up.
|
||||
|
|
|
@ -5,7 +5,7 @@ description: How to backup and restore keyfiles and blockchain data
|
|||
|
||||
**Keep secure backups of your keystore and password!**
|
||||
|
||||
## Data Directory
|
||||
## Data Directory {#data-directory}
|
||||
|
||||
All data relating to a specific Geth instance gets written inside a data directory. The default data directory locations are platform specific:
|
||||
|
||||
|
@ -19,7 +19,7 @@ To configure the location of the data directory, the `--datadir` parameter can b
|
|||
|
||||
It is important to backup the files in the keystore securely. These files are encrypted using an account password. This needs to be securely backed up too. There is no way to decrypt the keys without the password!
|
||||
|
||||
## Cleanup
|
||||
## Cleanup {#cleanup}
|
||||
|
||||
Geth's blockchain and state databases can be removed with:
|
||||
|
||||
|
@ -29,7 +29,7 @@ geth removedb
|
|||
|
||||
This is useful for deleting an old chain and sync'ing to a new one. It only affects data directories that can be re-created on synchronisation and does not touch the keystore.
|
||||
|
||||
## Blockchain Import/Export
|
||||
## Blockchain Import/Export {#blockchain-import-export}
|
||||
|
||||
Export the blockchain in binary format with:
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ obtained at any time from your Geth instance by running:
|
|||
geth --help
|
||||
```
|
||||
|
||||
## Commands
|
||||
## Commands {#commands}
|
||||
|
||||
```
|
||||
NAME:
|
||||
|
|
|
@ -3,7 +3,7 @@ title: Geth fundamentals
|
|||
description: Documentation for foundational Geth topics
|
||||
---
|
||||
|
||||
## Geth fundamentals
|
||||
## Geth fundamentals {#geth-fundamentals}
|
||||
|
||||
This section includes documentation for foundational topics in Geth. The pages here will help you to understand how Geth works from a user perspective and under the hood.
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ Read more about the reasons to run nodes on [ethereum.org](https://ethereum.org/
|
|||
|
||||
{% include note.html content=" Geth light clients **do not currently work** on proof-of-stake Ethereum. New light clients that work with the proof-of-stake consensus engine are expected to ship soon!" %}
|
||||
|
||||
## Light node vs full node
|
||||
## Light node vs full node {#light-node-vs-full-node}
|
||||
|
||||
Running Geth in light mode has the following advantages for users:
|
||||
|
||||
|
@ -25,7 +25,7 @@ However, the cost of this performance increase is that a light Geth node depends
|
|||
|
||||
A light client can be used to query data from Ethereum and submit transactions, acting as a locally-hosted Ethereum wallet. However they have different security guarantees than full nodes. Because they don't keep local copies of the Ethereum state, light nodes can't validate the blocks in the same way as the full nodes. Instead they fetch block headers by requesting them from full nodes and check their proof-of-work (PoW), assuming the heaviest chain is valid. This means that it is sensible to wait until a few additional blocks have been confirmed before trusting the validity of a recently-mined transaction.
|
||||
|
||||
### Running a light server
|
||||
### Running a light server {#running-light-server}
|
||||
|
||||
Full node operators that choose to enable light serving altruistically enable other users to run light clients. This is good for Ethereum because it makes it easier for a wider population of users to interact with Ethereum without using trusted intermediaries. However, there is naturally a limit to how much resource a node operator is able and willing to dedicate to serving light clients. Therefore, the command that enables light serving requires arguments that define the upper bound on resource allocation. The value given is in percent of a processing thread, for example `--light.serve 300` enables light-serving and dedicates three processing threads to it.
|
||||
|
||||
|
@ -37,7 +37,7 @@ The whole command for starting Geth with a light server could look as follows:
|
|||
geth --light.serve 50 --txlookuplimit 0
|
||||
```
|
||||
|
||||
### Running a light client
|
||||
### Running a light client {#running-light-client}
|
||||
|
||||
Running a light client simply requires Geth to be started in light mode. It is likely that a user would also want to interact with the light node using, for example, RPC. This can be enabled using the `--http` command.
|
||||
|
||||
|
@ -49,7 +49,7 @@ Data can be requested from this light Geth instance in the same way as for a ful
|
|||
|
||||
It's also possible to send transactions. However, light clients are not connected directly to Ethereum Mainnet but to a network of light servers that connect to Ethereum Mainnet. This means a transaction submitted by a light client is received first by a light server that then propagates it to full-node peers on the light-client's behalf. This reliance on honest light-servers is one of the trust compromises that comes along with running a light node instead of a full node.
|
||||
|
||||
### Ultra light clients
|
||||
### Ultra light clients {#ultra-light-client}
|
||||
|
||||
Geth has an even lighter sync mode called ultra light client (ULC). The difference between light mode and ultra-light mode is that a ULC doesn't check the PoW in block headers. There is an assumption that the ULC has access to one or more trusted light servers. This option has the greatest trust assumptions but the smallest resource requirement.
|
||||
|
||||
|
@ -59,6 +59,6 @@ To start an ultra-light client, the enode addresses of the trusted light servers
|
|||
geth --syncmode light --ulc.servers "enode://...,enode://..." --http --http.api "eth,debug"
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Running a full node is the most trustless way to interact with Ethereum. However, Geth provides a low-resource "light" mode that can be run on modest computers and requires much less disk space. The trade-offs are additional trust assumptions and a small pool of light-serving peers to connect to.
|
||||
|
|
|
@ -7,7 +7,7 @@ A Geth node continually reports messages to the console allowing users to monito
|
|||
|
||||
Note that there are a large number of log messages covering a wide range of possible scenarios for a Geth node. This page will only address a subset of commonly seen messages. For more, see the [Geth Github](https://github.com/ethereum/go-ethereum), [Discord](https://discord.gg/WHNkYDsAKU) or search on [ethereum.stackexchange](https://ethereum.stackexchange.com/). Log messages are usually sufficiently self-descrining that they do not require additional explanation.
|
||||
|
||||
## Configuring log messages
|
||||
## Configuring log messages {#configuring-log-messages}
|
||||
|
||||
Log messages are displayed to the console by default. The messages can be tuned to be more or less detailed by passing `--verbosity` and a value between 0 and 6 to Geth at startup:
|
||||
|
||||
|
@ -29,7 +29,7 @@ Log messages can also be redirected so they are saved to a text file instead of
|
|||
geth --verbosity 5 >> /path/eth.log 2>&1
|
||||
```
|
||||
|
||||
### Startup
|
||||
### Startup {#startup}
|
||||
|
||||
When Geth starts up it immediately reports a fairly long page of configuration details and status reports that allow the user to confirm Geth is on the right network and operating in its intended modes. The basic structure of a log message is as follows:
|
||||
|
||||
|
@ -114,7 +114,7 @@ INFO [10-04|10:21:03.100] Looking for peers peercount=0 t
|
|||
|
||||
The logs above relate to Geth starting up its peer-to-peer components and seeking other nodes to connect to. The long address reported to `Started P2P networking` is the nodes own enode address. The `IPC Endpoint` is the location of the node's IPC file that can be used to connect a Javascript console. There is a log message confirming that a JWT secret was generated and reporting its path. This is required to authenticate communication between Geth and the consensus client. There are also messages here reporting on the HTTP server that can be used to send requests to Geth. There should be two HTTP servers - one for interacting with Geth (defaults to `localhost:8545`) and one for communication with the consensus client (defaults to `localhost:8551`).
|
||||
|
||||
### Syncing
|
||||
### Syncing {#syncing}
|
||||
|
||||
The default for Geth is to sync in snap mode. This requires a block header to be provided to Geth by the consensus client. The header is then used as a target to sync to. Geth requests block headers from its peers that are parents of the target until there is a continuous chain of sequential headers of sufficient length. Then, Geth requests block bodies and receipts for each header and simultaneously starts downloading state data. This state data is stored in the form of a [Patricia Merkle Trie](https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/). Only the leaves of the trie are downloaded, the full trie structure is then locally regenerated from the leaves up. Meanwhile, the blockchain continues to progress and the target header is updated. This means some of the regenerated state data needs to be updated. This is known as _healing_.
|
||||
|
||||
|
@ -174,7 +174,7 @@ INFO [10-03|15:34:01.336] Forkchoice requested sync to new head number=15,670
|
|||
|
||||
The message above indicates that the fork choice algorithm, which is run by the consensus client, has identified a new target Geth should sync up to. This redirects the sync to prevent syncing to an outdated target and is a natural part of syncing a live blockchain.
|
||||
|
||||
## Transaction logs
|
||||
## Transaction logs {#transaction-logs}
|
||||
|
||||
Transactions submitted over local IPC, Websockets or HTTP connections are reported in the console logs. For example, a simple ETH transaction appears in the console logs as follows:
|
||||
|
||||
|
@ -184,7 +184,7 @@ INFO [09-06|01:31:59.910] Submitted transaction hash=0x2893b70483bf1
|
|||
|
||||
Other user actions have similar log messages that are displayed to the console.
|
||||
|
||||
## Common warnings
|
||||
## Common warnings {#common-warnings}
|
||||
|
||||
There are many warnings that can be emitted by Geth as part of its normal operation. However, some are asked about especially frequently on the [Geth Github](https://github.com/ethereum/go-ethereum) and [Discord](https://discord.gg/WHNkYDsAKU) channel.
|
||||
|
||||
|
@ -212,6 +212,6 @@ WARN [10-03 | 13:15:56.543] Dropping unsynced node during sync id = e2fdc0d92
|
|||
|
||||
This message indicates that a peer is being dropped because it is not fully synced. This is normal - the necessary data will be requested from an alternative peer instead.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
There are a wide range of log messages that are emitted while Geth is running. The level of detail in the logs can be configured using the `verbosity` flag at startup. This page has outlined some of the common messages users can expect to see when Geth is run with default verbosity, without attempting to be comprehensive. For more, please see the [Geth Github](https://github.com/ethereum/go-ethereum) and [Discord](https://discord.gg/WHNkYDsAKU).
|
||||
|
|
|
@ -13,19 +13,19 @@ Ethereum wasn't always secured this way. Originally, a proof-of-work based conse
|
|||
Much more information about mining, including details about the specific algorithm
|
||||
("Ethash") used by Ethereum nodes is available on [ethereum.org](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/mining-algorithms/ethash).
|
||||
|
||||
## CPU vs GPU
|
||||
## CPU vs GPU {#cpu-vs-gpu}
|
||||
|
||||
Ethereum mining used an algorithm called ["Ethash"](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/mining-algorithms/ethash). Geth includes a CPU miner which runs Ethash within the Geth process. Everything required to mine on a CPU is bundled with Geth. However, to mine using GPUs an additional piece of third-party software is required. The most commonly used GPU mining software is [Ethminer](https://github.com/ethereum-mining/ethminer).
|
||||
|
||||
Regardless of the mining method, the blockchain must be fully synced before mining is started, otherwise the miner will build on an outdated side chain,meaning block rewards will not be recognized by the main network.
|
||||
|
||||
## GPU Mining
|
||||
## GPU Mining {#gpu-mining}
|
||||
|
||||
### Installing Ethminer
|
||||
### Installing Ethminer {#installing-ethminer}
|
||||
|
||||
The Ethminer software can be installed from a downloaded binary or built from source. The relevant downloads and installation instructions are available from the [Ethminer Github](https://github.com/ethereum-mining/ethminer/#build). Standalone executables are available for Linux, macOS and Windows.
|
||||
|
||||
### Using Ethminer with Geth
|
||||
### Using Ethminer with Geth {#using-ethminer}
|
||||
|
||||
An account to receive block rewards must first be defined. The address of the account is all that is required to start mining - the mining rewards will be credited to that address. This can be an existing address or one that is newly created by Geth. More detailed instructions on creating and importing accounts are available on the [Account Management](/docs/interface/managing-your-accounts) page.
|
||||
|
||||
|
@ -95,7 +95,7 @@ Note that the Geth command `miner.hashrate` only works for CPU mining - it alway
|
|||
|
||||
More verbose logs can be configured using `-v` and a value between 0-9. The Ethash algorithm is [memory-hard](https://crypto.stackexchange.com/questions/84002/memory-hard-vs-memory-bound-functions) and requires a large dataset to be loaded into memory. Each GPU requires 4-5 GB of RAM. The error message `Error GPU mining. GPU memory fragmentation?` indicates that there is insufficient memory available.
|
||||
|
||||
## CPU Mining with Geth
|
||||
## CPU Mining with Geth {#cpu-mining-with-geth}
|
||||
|
||||
When Geth is started it is not mining by default. Unless it is specifically instructed to mine, it acts only as a node, not a miner. Geth starts as a (CPU) miner if the `--mine` flag is provided. The `--miner.threads` parameter can be used to set the number parallel mining threads (defaulting to the total number of processor cores).
|
||||
|
||||
|
@ -175,6 +175,6 @@ in its own local blockchain the account balance appears higher because the block
|
|||
|
||||
The logs show locally mined blocks confirmed after 5 blocks.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
The page describes how to start Geth as a mining node. Mining can be done on CPUs - in which case Geth's built-in miner can be used - or on GPUs which requires third party software. Mining is **no longer used to secure Ethereum Mainnet**.
|
||||
|
|
|
@ -3,8 +3,6 @@ title: Node architecture
|
|||
description: Introduction to how Ethereum nodes are organized and where Geth fits.
|
||||
---
|
||||
|
||||
## Node architecture
|
||||
|
||||
An Ethereum node is composed of two clients: an [execution client](https://ethereum.org/en/developers/docs/nodes-and-clients/#execution-clients) and a [consensus client](https://ethereum.org/en/developers/docs/nodes-and-clients/#consensus-clients). Geth is an [execution client](https://ethereum.org/en/developers/docs/nodes-and-clients/#execution-clients). Originally, an execution client alone was enough to run a full Ethereum node. However, ever since Ethereum turned off [proof-of-work](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/) and implemented [proof-of-stake](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/), Geth has needed to be coupled to another piece of software called a [“consensus client”](https://ethereum.org/en/developers/docs/nodes-and-clients/#consensus-clients) in order to keep track of the Ethereum blockchain.
|
||||
|
||||
The execution client (Geth) is responsible for transaction handling, transaction gossip, state management and supporting the Ethereum Virtual Machine ([EVM])(https://ethereum.org/en/developers/docs/evm/). However, Geth is **not** responsible for block building, block gossiping or handling consensus logic. These are in the remit of the consensus client.
|
||||
|
@ -15,7 +13,7 @@ The relationship between the two Ethereum clients is shown in the schematic belo
|
|||
|
||||
For this two-client structure to work, consensus clients must be able to pass bundles of transactions to Geth to be executed. Executing the transactions locally is how the client validates that the transactions do not violate any Ethereum rules and that the proposed update to Ethereum’s state is correct. Likewise, when the node is selected to be a block producer the consensus client must be able to request bundles of transactions from Geth to include in the new block. This inter-client communication is handled by a local RPC connection using the [engine API](https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md).
|
||||
|
||||
## What does Geth do?
|
||||
## What does Geth do? {#what-does-geth-do}
|
||||
|
||||
As an execution client, Geth is responsible for creating the execution payloads - the list of transactions, updated state trie plus other execution related data - that consensus clients include in their blocks. Geth is also responsible for re-executing transactions that arrive in new blocks to ensure they are valid. Executing transactions is done on Geth's embedded computer, known as the Ethereum Virtual Machine (EVM).
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ geth --goerli --syncmode "full" ... dumpconfig > goerli.toml
|
|||
geth --goerli --config goerli.toml
|
||||
```
|
||||
|
||||
## Finding peers
|
||||
## Finding peers {#finding-peers}
|
||||
|
||||
Geth continuously attempts to connect to other nodes on the network until it has enough peers. If UPnP (Universal Plug and Play) is enabled at the router or Ethereum is run on an Internet-facing server, it will also accept connections from other nodes. Geth finds peers using the [discovery protocol](https://ethereum.org/en/developers/docs/networking-layer/#discovery). In the discovery protocol, nodes exchange connectivity details and then establish sessions ([RLPx](https://github.com/ethereum/devp2p/blob/master/rlpx.md)). If the nodes support compatible sub-protocols they can start exchanging Ethereum data [on the wire](https://ethereum.org/en/developers/docs/networking-layer/#wire-protocol).
|
||||
|
||||
|
@ -32,7 +32,7 @@ geth --bootnodes enode://pubkey1@ip1:port1,enode://pubkey2@ip2:port2,enode://pub
|
|||
|
||||
There are scenarios where disabling the discovery process is useful, for example for running a local test node or an experimental test network with known, fixed nodes. This can be achieved by passing the `--nodiscover` flag to Geth at startup.
|
||||
|
||||
## Connectivity problems
|
||||
## Connectivity problems {#connectivity-problems}
|
||||
|
||||
There are occasions when Geth simply fails to connect to peers. The common reasons for this are:
|
||||
|
||||
|
@ -44,7 +44,7 @@ There are occasions when Geth simply fails to connect to peers. The common reaso
|
|||
|
||||
- The public test network Geth is connecting to might be deprecated or have a low number of active nodes that are hard to find. In this case, the best action is to switch to an alternative test network.
|
||||
|
||||
## Checking Connectivity
|
||||
## Checking Connectivity {#checking-connectivity}
|
||||
|
||||
The `net` module has two attributes that enable checking node connectivity from the [interactive Javascript console](/docs/interface/javascript-console). These are `net.listening` which reports whether the Geth node is listening for inbound requests, and `peerCount` which returns the number of active peers the node is connected to.
|
||||
|
||||
|
@ -104,11 +104,11 @@ The `admin` module also includes functions for gathering information about the l
|
|||
}
|
||||
```
|
||||
|
||||
## Custom Networks
|
||||
## Custom Networks {#custom-networks}
|
||||
|
||||
It is often useful for developers to connect to private test networks rather than public testnets or Etheruem mainnet. These sandbox environments allow block creation without competing against other miners, easy minting of test ether and give freedom to break things without real-world consequences. A private network is started by providing a value to `--networkid` that is not used by any other existing public network ([Chainlist](https://chainlist.org)) and creating a custom `genesis.json` file. Detailed instructions for this are available on the [Private Networks page](/docs/interface/private-network).
|
||||
|
||||
## Static nodes
|
||||
## Static nodes {#static-nodes}
|
||||
|
||||
Geth also supports static nodes. Static nodes are specific peers that are always connected to. Geth reconnects to these peers automatically when it is restarted. Specific nodes are defined to be static nodes by adding their enode addresses to a config file. The easiest way to create this config file is to run:
|
||||
|
||||
|
@ -132,7 +132,7 @@ admin.addPeer(
|
|||
);
|
||||
```
|
||||
|
||||
## Peer limit
|
||||
## Peer limit {#peer-limit}
|
||||
|
||||
It is sometimes desirable to cap the number of peers Geth will connect to in order to limit on the computational and bandwidth cost associated with running a node. By default, the limit is 50 peers, however, this can be updated by passing a value to `--maxpeers`:
|
||||
|
||||
|
@ -140,7 +140,7 @@ It is sometimes desirable to cap the number of peers Geth will connect to in ord
|
|||
geth <otherflags> --maxpeers 15
|
||||
```
|
||||
|
||||
## Trusted nodes
|
||||
## Trusted nodes {#trusted-nodes}
|
||||
|
||||
Trusted nodes can be added to `config.toml` in the same way as for static nodes. Add the trusted node's enode address to the `TrustedNodes` field in `config.toml` before starting Geth with `--config config.toml`.
|
||||
|
||||
|
@ -152,6 +152,6 @@ admin.addTrustedPeer(
|
|||
);
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Geth connects to Ethereum Mainnet by default. However, this behaviour can be changed using combinations of command line flags and files. This page has described the various options available for connecting a Geth node to Ethereum, public testnets and private networks. Remember that to connect to a proof-of-stake network (e.g. Ethereum Mainnet, Goerli, Sepolia) a consensus client is also required.
|
||||
|
|
|
@ -10,7 +10,7 @@ within the bounds of the local hardware (e.g. every month or so for a 1TB disk).
|
|||
|
||||
To prune a Geth node at least 40 GB of free disk space is recommended. This means pruning cannot be used to save a hard drive that has been completely filled. A good rule of thumb is to prune before the node fills ~80% of the available disk space.
|
||||
|
||||
## Pruning rules
|
||||
## Pruning rules {#pruning-rules}
|
||||
|
||||
1. Do not try to prune an archive node. Archive nodes need to maintain ALL historic data by definition.
|
||||
2. Ensure there is at least 40 GB of storage space still available on the disk that will be pruned. Failures have been reported with ~25GB of free space.
|
||||
|
@ -20,7 +20,7 @@ To prune a Geth node at least 40 GB of free disk space is recommended. This mean
|
|||
|
||||
With these rules satisfied, Geth's database can be pruned.
|
||||
|
||||
## How pruning works
|
||||
## How pruning works {#how-pruning-works}
|
||||
|
||||
Pruning uses snapshots of the state database as an indicator to determine which nodes in the state trie can be kept and which ones are stale and can be discarded. Geth identifies the target state trie based on a stored snapshot layer which has at least 128 block confirmations on top (for surviving reorgs) data that isn't part of the target state trie or genesis state.
|
||||
|
||||
|
@ -32,7 +32,7 @@ Geth prunes the database in three stages:
|
|||
|
||||
There may be a period of >1 hour during the Compacting Database stage with no log messages at all. This is normal, and the pruning should be left to run until finally a log message containing the phrase `State pruning successful` appears (i.e. do not restart Geth yet!). That message indicates that the pruning is complete and Geth can be started.
|
||||
|
||||
## Pruning command
|
||||
## Pruning command {#pruning-command}
|
||||
|
||||
For a normal Geth node, Geth should be stopped and the following command executed to start a offline state prune:
|
||||
|
||||
|
@ -51,11 +51,11 @@ sudo systemctl start geth # restart geth
|
|||
|
||||
The pruning could take 4-5 hours to complete. Once finished, restart Geth.
|
||||
|
||||
## Troubleshooting
|
||||
## Troubleshooting {#troubleshooting}
|
||||
|
||||
Messages about "state snapshot generation" indicate that a snapshot is not fully generated. This suggests either the `--datadir` is not correct or Geth ran out of time to complete the snapshot generation and the pruning began before the snapshot was completed. In either case, the best course of action is to stop Geth, run it normally again (no pruning) until the snapshot is definitely complete and at least 128 blocks exist on top of it, then try pruning again.
|
||||
|
||||
## Further Reading
|
||||
## Further Reading {#further-reading}
|
||||
|
||||
[Ethereum Foundation blog post for Geth v1.10.0](https://blog.ethereum.org/2021/03/03/geth-v1-10-0/)
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ title: Security
|
|||
description: A primer on Geth security best practice.
|
||||
---
|
||||
|
||||
## Downloading Geth
|
||||
## Downloading Geth {#downloading-geth}
|
||||
|
||||
Download Geth using the links on the [Downloads](/downloads) page. The SHA256 hashes of the downloaded files can be used to confirm precise consistency with our releases. This protects against malicious code being inadvertently downloaded from an adversarial source. The same measures should also be taken to download trusted consensus client software.
|
||||
|
||||
## Networking security
|
||||
## Networking security {#networking-security}
|
||||
|
||||
The local machine's firewall settings should:
|
||||
|
||||
|
@ -15,16 +15,14 @@ The local machine's firewall settings should:
|
|||
- Allow traffic on `TCP 30303` or whichever custom port has been defined for peer-to-peer communications. This allows the node to connect to peers.
|
||||
- Allow traffic on `UDP 30303` or whichever custom port has been defined for peer-to-peer communications. This allows node discovery.
|
||||
|
||||
## Account security
|
||||
## Account security {#account-security}
|
||||
|
||||
Account security comes down to keeping private keys and account passwords backed up and inaccessible to adversaries. This is something that users take responsibility for. Geth provides an encrypted store for keys that are unlocked using an account password. If the key files or the passwors are lost, the account is impossible to access and the funds are effectively lost forever. If access to the unencrypted keys is obtained by an adversary they gain control of any funds associated with the account.
|
||||
|
||||
Geth has built-in account management tools that are sufficiently secure for most purposes. However, Clef is recommended as an external account management and signing tool. It can be run decoupled from Geth and can even be run on dedicated secure external hardware such as a VM or a secure USB drive. This is considered best practise because the user is required to manually review all actions that touch sensitive data, except where specific predefined rules are implemented. Signing is done locally to Clef rather than giving key access to a node.
|
||||
|
||||
Geth allows account unlocking by passing account passwords at startup. This unlocks the account all the while that Geth is running. This is not allowed when `http` traffic is enabled, even with appropriate firewall settings. The combination of `http` and `-unlock` poses too much of a security risk because an attacker able to access the node over the exposed HTTP port would be able to make JSON-RPC requests to the node from the unlocked account, including sending funds to other addresses.
|
||||
Geth has built-in account management tools. However, Clef is recommended as an external account management and signing tool. It can be run decoupled from Geth and can even be run on dedicated secure external hardware such as a VM or a secure USB drive. This is considered best practise because the user is required to manually review all actions that touch sensitive data, except where specific predefined rules are implemented. Signing is done locally to Clef rather than giving key access to a node. Geth's built-in management tools are intended to be deprecated in the near future.
|
||||
|
||||
**Back up your keystore and passwords safely and securely!**
|
||||
|
||||
## Other security considerations
|
||||
## Other security considerations {#other-security}
|
||||
|
||||
Even with a perfectly secure node, users can still be manipulated by attackers into exposing security weaknesses or inadvertently interact with insecure smart contracts. For an overview, please see the Ethereum [security best practise webpage](https://ethereum.org/en/security) and this introduction to [smart contract security](https://ethereum.org/en/developers/docs/smart-contracts/security).
|
||||
|
|
|
@ -5,15 +5,20 @@ description: Introduction to Geth's sync modes
|
|||
|
||||
Syncing is the process by which Geth catches up to the latest Ethereum block and current global state. There are several ways to sync a Geth node that differ in their speed, storage requirements and trust assumptions. Now that Ethereum uses proof-of-stake based consensus, a consensus client is required for Geth to sync.
|
||||
|
||||
## Full nodes
|
||||
## Full nodes {#full-nodes}
|
||||
|
||||
There are two types of full node that use different mechanisms to sync up to the head of the chain:
|
||||
|
||||
### Snap (default)
|
||||
### Snap (default) {#snap-sync}
|
||||
|
||||
A snap sync'd node holds the most recent 128 block states in memory, so transactions in that range are always quickly accessible. However, snap-sync only starts processing from a relatively recent block (as opposed to genesis for a full node). Between the initial sync block and the 128 most recent blocks, the node stores occasional checkpoints that can be used to rebuild the state on-the-fly. This means transactions can be traced back as far as the block that was used for the initial sync. Tracing a single transaction requires reexecuting all preceding transactions in the same block **and** all preceding blocks until the previous stored snapshot. Snap-sync'd nodes are therefore full nodes, with the only difference being the initial synchronization required a checkpoint block to sync from instead of independently verifying the chain all the way from genesis. Snap sync then only verifies the proof-of-work and ancestor-child block progression and assumes that the state transitions are correct rather than re-executing the transactions in each block to verify the state changes. Snap sync is much faster than block-by-block sync. To start a node with snap sync pass `--syncmode snap` at startup.
|
||||
Snap sync starts froma relatively recent block and syncs from there to the head of the chain, keeping only the most recent 128 block states in memory. The block header to sync up to is provided by the consensus client. Between the initial sync block and the 128 most recent blocks, the node stores occasional snapshots that can be used to rebuild any intermediate state "on-the-fly". The difference between the snap-synced node and a full block-by-block synced node is that a snap synced node started from an initial checkpoint that was more recent than the genesis block. Snap sync is much faster than a full block-by-block sync from genesis. To start a node with snap sync pass `--syncmode snap` at startup.
|
||||
|
||||
Snap sync starts by downloading the headers for a chunk of blocks. Once the headers have been verified, the block bodies and receipts for those blocks are downloaded. In parallel, Geth also sync begins state-sync. In state-sync, Geth first downloads the leaves of the state trie for each block without the intermediate nodes along with a range proof. The state trie is then regenerated locally. The state download is the part of the snap-sync that takes the most time to complete and the progress can be monitored using the ETA values in the log messages. However, the blockchain is also progressing at the same time and invalidating some of the regenerated state data. This means it is also necessary to have a 'healing' phase where errors in the state are fixed. It is not possible to monitor the progress of the state heal because the extent of the errors cannot be known until the current state has already been regenerated. Geth regularly reports `Syncing, state heal in progress` regularly during state heal - this informs the user that state heal has not finished. It is also possible to confirm this using `eth.syncing` - if this command returns `false` then the node is in sync. If it returns anything other than `false` then syncing is still in progress.
|
||||
![state pruning options](/public/images/docs/state-pruning.png)
|
||||
_This image shows the state stored by each sync-mode - red indicates stored state. The full width of each line represents origin to present head_
|
||||
|
||||
Snap sync works by first downloading the headers for a chunk of blocks. Once the headers have been verified, the block bodies and receipts for those blocks are downloaded. In parallel, Geth also sync begins state-sync. In state-sync, Geth first downloads the leaves of the state trie for each block without the intermediate nodes along with a range proof. The state trie is then regenerated locally.
|
||||
|
||||
The state download is the part of the snap-sync that takes the most time to complete and the progress can be monitored using the ETA values in the log messages. However, the blockchain is also progressing at the same time and invalidating some of the regenerated state data. This means it is also necessary to have a 'healing' phase where errors in the state are fixed. It is not possible to monitor the progress of the state heal because the extent of the errors cannot be known until the current state has already been regenerated. Geth regularly reports `Syncing, state heal in progress` during state healing - this informs the user that state heal has not finished. It is also possible to confirm this using `eth.syncing` - if this command returns `false` then the node is in sync. If it returns anything other than `false` then syncing is still in progress.
|
||||
|
||||
The healing has to outpace the growth of the blockchain, otherwise the node will never catch up to the current state. There are some hardware factors that determine the speed of the state healing (speed of disk read/write and internet connection) and also the total gas used in each block (more gas means more changes to the state that have to be handled).
|
||||
|
||||
|
@ -25,19 +30,19 @@ To summarize, snap sync progresses in the following sequence:
|
|||
|
||||
**Note** Snap sync is the default behaviour, so if the `--syncmode` value is not passed to Geth at startup, Geth will use snap sync. A node that is started using `snap` will switch to block-by-block sync once it has caught up to the head of the chain.
|
||||
|
||||
### Full
|
||||
### Full {#full-sync}
|
||||
|
||||
A full sync generates the current state by executing every block starting from the genesis block. A full sync indendently verifies proof-of-work and block provenance as well as all state transitions by re-executing the transactions in the entire historical sequence of blocks. Only the most recent 128 block states are stored in a full node - older block states are pruned periodically and represented as a series of checkpoints from which any previous state can be regenerated on request. 128 blocks is about 25.6 minutes of history with a block time of 12 seconds.
|
||||
A full blobk-by-block sync generates the current state by executing every block starting from the genesis block. A full sync indendently verifies block provenance as well as all state transitions by re-executing the transactions in the entire historical sequence of blocks. Only the most recent 128 block states are stored in a full node - older block states are pruned periodically and represented as a series of checkpoints from which any previous state can be regenerated on request. 128 blocks is about 25.6 minutes of history with a block time of 12 seconds.
|
||||
|
||||
To create a full node pass `--syncmode full` at startup.
|
||||
|
||||
## Archive nodes
|
||||
## Archive nodes {#archive-nodes}
|
||||
|
||||
An archive node is a node that retains all historical data right back to genesis. There is no need to regenerate any data from checkpoints because all data is directly available in the node's own storage. Archive nodes are therefore ideal for making fast queries about historical states. At the time of writing (September 2022) a full archive node that stores all data since genesis occupies nearly 12 TB of disk space (keep up with the current size on [Etherscan](https://etherscan.io/chartsync/chainarchive)). Archive nodes are created by configuring Geth's garbage collection so that old data is never deleted: `geth --syncmode full --gcmode archive`.
|
||||
|
||||
It is also possible to create a partial/recent archive node where the node was synced using `snap` but the state is never pruned. This creates an archive node that saves all state data from the point that the node first syncs. This is configured by starting Geth with `--syncmode snap --gcmode archive`.
|
||||
|
||||
## Light nodes
|
||||
## Light nodes {#light-nodes}
|
||||
|
||||
A light node syncs very quickly and stores the bare minimum of blockchain data. Light nodes only process block headers, not entire blocks. This greatly reduces the computation time, storage and bandwidth required relative to a full node. This means light nodes are suitable for resource-constrained devices and can catch up to the head of the chain much faster when they are new or have been offline for a while. The trade-off is that light nodes rely heavily on data served by altruistic full nodes. A light client can be used to query data from Ethereum and submit transactions, acting as a locally-hosted Ethereum wallet. However, because they don't keep local copies of the Ethereum state, light nodes can't validate blocks in the same way as full nodes - they receive a proof from the full node and verify it against their local header chain. To start a node in light mode, pass `--syncmode light`. Be aware that full nodes serving light data are relative scarce so light nodes can struggle to find peers. **Light nodes are not currently working on proof-of-stake Ethereum**.
|
||||
|
||||
|
@ -47,26 +52,26 @@ The following diagram shows how Geth stores state data in the different sync mod
|
|||
|
||||
![state pruning options](/public/images/docs/state-pruning.png)
|
||||
|
||||
## Consensus layer syncing
|
||||
## Consensus layer syncing {#consensus-layer-syncing}
|
||||
|
||||
Now that Ethereum has switched to proof-of-stake, all consensus logic and block propagation is handled by consensus clients. This means that syncing the blockchain is a process shared between the consensus and execution clients. Blocks are downloaded by the consensus client and verified by the execution client. In order for Geth to sync, it requires a header from its connected consensus client. Geth does not import any data until it is instructed to by the consensus client. **Geth cannot sync without being connected to a consensus client**. This includes block-by-block syncing from genesis.
|
||||
Now that Ethereum has switched to proof-of-stake, all consensus logic and block propagation is handled by consensus clients. This means that syncing the blockchain is a process shared between the consensus and execution clients. Blocks are downloaded by the consensus client and verified by the execution client. In order for Geth to sync, it requires a header from its connected consensus client. Geth does not import any data until it is instructed to by the consensus client. **Geth cannot sync without being connected to a consensus client**. This includes block-by-block syncing from genesis. The consensus client is required to provide a header from the tip of the chain that Geth can sync towards - without it, Geth cannot know that it has followed the right sequence of blocks.
|
||||
|
||||
Once a header is available to use as a syncing target, Geth retrieves all headers between that target header and the local header chain in reverse chronological order. These headers show that the sequence of blocks is correct because the parenthashes link one block to the next right up to the target block. Eventually, the sync will reach a block held in the local database, at which point the local data and the target data are considered 'linked' and there is a very high chance the node is syncing the correct chain. The block bodies are then downloaded and then the state data. The consensus client can update the target header - as long as the syncing outpaces the growth of the blockchain then the node will eventually get in sync.
|
||||
|
||||
There are two ways for the consensus client to find a block header that Geth can use as a sync target: optimistic syncing and checkpoint syncing:
|
||||
|
||||
### Optimistic sync
|
||||
### Optimistic sync {#optimistic-sync}
|
||||
|
||||
Optimistic sync downloads blocks before the execution client has validated them. In optimistic sync the node assumes the data it receives from its peers is correct during the downloading phase but then retroactively verifies each downloaded block. Nodes are not allowed to attest or propose blocks while they are still 'optimistic' because they can't yet guarantee their view of the head of the chain is correct.
|
||||
|
||||
Read more in the [optimistic sync specs](https://github.com/ethereum/consensus-specs/blob/dev/sync/optimistic.md).
|
||||
|
||||
### Checkpoint sync
|
||||
### Checkpoint sync {#checkpoint-sync}
|
||||
|
||||
Alternatively, the consensus client can grab a checkpoint from a trusted source which provides a target state to sync up to, before switching to full sync and verifying each block in turn. In this mode, the node trusts that the checkpoint is correct. There are many possible sources for this checkpoint - the gold standard would be to get it out-of-band from another trusted friend, but it could also come from block explorers or [public APIs/web apps](https://eth-clients.github.io/checkpoint-sync-endpoints/).
|
||||
Alternatively, the consensus client can grab a checkpoint from a trusted source which provides a target state to sync up to, before switching to full sync and verifying each block in turn. In this mode, the node trusts that the checkpoint is correct. There are many possible sources for this checkpoint - the gold standard would be to get it out-of-band from another trusted friend, but it could also come from block explorers or [public APIs/web apps](https://eth-clients.github.io/checkpoint-sync-endpoints/). Checkpoint sync is very fast - a consensus cleint should be able to sync in a few minutes using this method.
|
||||
|
||||
Please see the pages on [syncing](/docs/interface/sync-modes) for more detail. For troubleshooting, please see the `Syncing` section on the [console log messages](/docs/interface/logs) page.
|
||||
For troubleshooting, please see the `Syncing` section on the [console log messages](/docs/interface/logs) page.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
There are several ways to sync a Geth node. The default is to use snap sync to create a full node. This verifies all blocks using some recent block that is old enough to be safe from re-orgs as a sync target. A trust-minimized alternative is full-sync, which verifies every block since genesis. These modes drop state data older than 128 blocks, keeping only checkpoints that enable on-request regeneration of historical states. For rapid queries of historical data an archive node is required. Archive nodes keep local copies of all historical data right back to genesis - currently about 12 TB and growing. The opposite extreme is a light node that doesn't store any blockchain data - it requests everything from full nodes. These configurations are controlled by passing `full`, `snap` or `light` to `--syncmode` at startup. For an archive node, `--syncmode` should be `full` and `--gcmode` should be set to `archive`. Currently, due to the transition to proof-of-stake, light-sync does not work (new light client protocols are being developed).
|
||||
There are several ways to sync a Geth node. The default is to use snap sync to create a full node. Full nodes can be created by syncing block-by-block from genesis (full-sync) or by starting at an intermediate checkpoint block (snap-sync). By default, these modes prune state data older than 128 blocks, keeping only checkpoints that enable on-request regeneration of historical states. For rapid queries of historical data an archive node is required. Archive nodes keep local copies of all historical data right back to genesis - currently about 12 TB and growing. Partial archive nodes can be created by snap-syncign a node and turning off state-pruning to create a node that keeps all states since the initial sync block. Currently, due to the transition to proof-of-stake, light-sync does not work (new light client protocols are being developed).
|
||||
|
|
|
@ -7,7 +7,7 @@ Geth is an [execution client](https://ethereum.org/en/glossary/#execution-client
|
|||
|
||||
There are five consensus clients available, all of which connect to Geth in the same way. This page will outline how Geth can be set up with a consensus client to form a complete Ethereum node.
|
||||
|
||||
## Configuring Geth
|
||||
## Configuring Geth {#configuring-geth}
|
||||
|
||||
Geth can be downloaded and installed according to the instructions on the [Installing Geth](/docs/install-and-build/installing-geth) page. In order to connect to a consensus client, Geth must expose a port for the inter-client RPC connection.
|
||||
|
||||
|
@ -21,7 +21,7 @@ A complete command to start Geth so that it can connect to a consensus client lo
|
|||
geth --authrpc.addr localhost --authrpc.port 8551 --authrpc.vhosts localhost --authrpc.jwtsecret /tmp/jwtsecret
|
||||
```
|
||||
|
||||
## Consensus clients
|
||||
## Consensus clients {#consensus-clients}
|
||||
|
||||
There are currently five consensus clients that can be run alongside Geth. These are:
|
||||
|
||||
|
@ -43,17 +43,17 @@ The consensus client also needs the path to Geth's `jwt-secret` in order to auth
|
|||
|
||||
The consensus clients all expose a [Beacon API](https://ethereum.github.io/beacon-APIs) that can be used to check the status of the Beacon client or download blocks and consensus data by sending requests using tools such as [Curl](https://curl.se). More information on this can be found in the documentation for each consensus client.
|
||||
|
||||
## Validators
|
||||
## Validators {#validators}
|
||||
|
||||
Validators are responsible for securing the Ethereum blockchain. Validators have staked at least 32 ETH into a deposit contract and run validator software. Each of the consensus clients have their own validator software that is described in detail in their respective documentation. The easiest way to handle staking and validator key generation is to use the Ethereum Foundation [Staking Launchpad](https://launchpad.ethereum.org/). The Launchpad guides users through the process of generating validator keys and connecting the validator to the consensus client.
|
||||
|
||||
## Syncing
|
||||
## Syncing {#syncing}
|
||||
|
||||
Geth cannot sync until the connected consensus client is synced. This is because Geth needs a target head to sync to. The fastest way to sync a consensus client is using checkpoint sync. To do this, a checkpoint or a url to a checkpoint provider can be provided to the consensus client on startup. There are several sources for these checkpoints. The ideal scenario is to get one from a trusted node operator, organized out-of-band, and verified against a third node or a block explorer or checkpoint provider. Some clients also allow checkpoint syncing by HTTP API access to an existing Beacon node. There are also several [public checkpoint sync endpoints](https://eth-clients.github.io/checkpoint-sync-endpoints/).
|
||||
|
||||
Please see the pages on [syncing](/docs/fundamentals/sync-modes) for more detail. For troubleshooting, please see the `Syncing` section on the [console log messages](/docs/fundamentals/logs) page.
|
||||
|
||||
## Using Geth
|
||||
## Using Geth {#using-geth}
|
||||
|
||||
Geth is the portal for users to send transactions to Ethereum. The Geth Javascript console is available for this purpose, and the majority of the [JSON-RPC API](/docs/rpc/server) will remain available via web3js or HTTP requests with commands as json payloads. These options are explained in more detail on the [Javascript Console page](/docs/interface/javascript-console). The Javascript console can be started
|
||||
using the following command in a separate terminal (assuming Geth's IPC file is saved in `datadir`):
|
||||
|
@ -62,6 +62,6 @@ using the following command in a separate terminal (assuming Geth's IPC file is
|
|||
geth attach datadir/geth.ipc
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Now that Ethereum has implemented proof-of-stake, Geth users are required to install and run a consensus client. Otherwise, Geth will not be able to track the head of the chain. There are five consensus clients to choose from. This page provided an overview of how to choose a consensus client and configure Geth to connect to it.
|
||||
|
|
|
@ -1,431 +0,0 @@
|
|||
---
|
||||
title: Geth and Clef
|
||||
description: Guide to getting up and running with Geth using Clef as an external account management and signing tool.
|
||||
---
|
||||
|
||||
This page explains how to set up Geth and execute some basic tasks using the command line tools. In order to use Geth, the software must first be installed. There are several ways Geth can be installed depending on the operating system and the user's choice of installation method, for example using a package manager, container or building from source. Instructions for installing Geth can be found on the ["Install and Build"](/docs/getting_started/Installing-Geth) pages. Geth also needs to be connected to a consensus client in order to function as an Ethereum node. The tutorial on this page assumes Geth and a consensus client have been installed successfully and that a firewall has been configured to block external traffic to the JSON-RPC port `8545` see [Security](/content/docs/fundamentals/security).
|
||||
|
||||
This page provides step-by-step instructions covering the fundamentals of using Geth. This includes generating accounts, joining an Ethereum network, syncing the blockchain and sending ether between accounts. This tutorial uses [Clef](/docs/tools/Clef/Tutorial). Clef is an account management tool external to Geth itself that allows users to sign transactions. It is developed and maintained by the Geth team and is intended to eventually replace the account management tool built in to Geth.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
In order to get the most value from the tutorials on this page, the following skills are necessary:
|
||||
|
||||
- Experience using the command line
|
||||
- Basic knowledge about Ethereum and testnets
|
||||
- Basic knowledge about HTTP and JavaScript
|
||||
- Basic knowledge of node architecture and consensus clients
|
||||
|
||||
Users that need to revisit these fundamentals can find helpful resources relating to the command line [here](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line), Ethereum and its testnets [here](https://ethereum.org/en/developers/tutorials/), http [here](https://developer.mozilla.org/en-US/docs/Web/HTTP) and Javascript [here](https://www.javascript.com/learn). Information on node architecture can be found [here](/docs/fundamentals/node-architecture) and our guide for configuring Geth to connect to a
|
||||
consensus client is [here](/docs/getting_started/consensus-clients).
|
||||
|
||||
{% include note.html content="If Geth was installed from source on Linux, `make` saves the binaries for Geth and the associated tools in `/build/bin`. To run these programs it is convenient to move them to the top level project directory (e.g. running `mv ./build/bin/* ./`) from `/go-ethereum`. Then `./` must be prepended to the commands in the code snippets in order to execute a particular program, e.g. `./geth` instead of simply `geth`. If the executables are not moved then either navigate to the `bin` directory to run them (e.g. `cd ./build/bin` and `./geth`) or provide their path (e.g. `./build/bin/geth`). These instructions can be ignored for other installations." %}
|
||||
|
||||
## Background
|
||||
|
||||
Geth is an Ethereum client written in Go. This means running Geth turns a computer into an Ethereum node. Ethereum is a peer-to-peer network where information is shared directly between nodes rather than being managed by a central server. Every 12 seconds one node is randomly selected to generate a new block containing a list of transactions that nodes receiving the block should execute. This "block proposer" node sends the new block to its peers. On receiving a new block, each node checks that it is valid and adds it to their database. The sequence of discrete blocks is called a "blockchain".
|
||||
|
||||
The information provided in each block is used by Geth to update its "state" - the ether balance of each account on Ethereum and the data stored by each smart contract. There are two types of account: externally-owned accounts (EOAs) and contract accounts. Contract accounts execute contract code when they receive transactions. EOAs are accounts that users manage locally in order to sign and submit transactions. Each EOA is a public-private key pair, where the public key is used to derive a unique address for the user and the private key is used to protect the account and securely sign messages. Therefore, in order to use Ethereum,
|
||||
it is first necessary to generate an EOA (hereafter, "account"). This tutorial will guide the user through creating an account, funding it with ether and sending some to another address.
|
||||
|
||||
Read more about Ethereum accounts [here](https://ethereum.org/en/developers/docs/accounts/).
|
||||
|
||||
## Step 1: Generating accounts
|
||||
|
||||
There are several methods for generating accounts in Geth. This tutorial demonstrates how to generate accounts using Clef, as this is considered best practice, largely because it decouples the users' key management from Geth, making it more modular and flexible. It can also be run from secure USB sticks or virtual machines, offering security benefits. For convenience, this tutorial will execute Clef on the same computer that will also run Geth, although more secure options are available (see [here](https://github.com/ethereum/go-ethereum/blob/master/cmd/clef/docs/setup.md)).
|
||||
|
||||
An account is a pair of keys (public and private). Clef needs to know where to save these keys to so that they can be retrieved later. This information is passed to Clef as an argument. This is achieved using the following command:
|
||||
|
||||
```shell
|
||||
clef newaccount --keystore geth-tutorial/keystore
|
||||
```
|
||||
|
||||
The specific function from Clef that generates new accounts is `newaccount` and it accepts a parameter, `--keystore`, that tells it where to store the newly generated keys. In this example the keystore location is a new directory that will be created automatically: `geth-tutorial/keystore`.
|
||||
Clef will return the following result in the terminal:
|
||||
|
||||
```terminal
|
||||
WARNING!
|
||||
|
||||
Clef is an account management tool. It may, like any software, contain bugs.
|
||||
|
||||
Please take care to
|
||||
- backup your keystore files,
|
||||
- verify that the keystore(s) can be opened with your password.
|
||||
|
||||
Clef is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
Enter 'ok' to proceed:
|
||||
>
|
||||
```
|
||||
|
||||
This is important information. The `geth-tutorial/keystore` directory will soon contain a secret key that can be used to access any funds held in the new account. If it is compromised, the funds can be stolen. If it is lost, there is no way to retrieve the funds. This tutorial will only use dummy funds with no real world value, but when these steps are repeated on Ethereum mainnet is critical that the keystore is kept secure and backed up.
|
||||
|
||||
Typing `ok` into the terminal and pressing `enter` causes Clef to prompt for a password. Clef requires a password that is at least 10 characters long, and best practice would be to use a combination of numbers, characters and special characters. Entering a suitable password and pressing `enter` returns the following result to the terminal:
|
||||
|
||||
```terminal
|
||||
-----------------------
|
||||
DEBUG[02-10|13:46:46.436] FS scan times list="92.081µs" set="12.629µs" diff="2.129µs"
|
||||
INFO [02-10|13:46:46.592] Your new key was generated address=0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
WARN [02-10|13:46:46.595] Please backup your key file! path=keystore:///.../geth-tutorial/keystore/UTC--2022-02-07T17-19-56.517538000Z--ca57f3b40b42fcce3c37b8d18adbca5260ca72ec
|
||||
WARN [02-10|13:46:46.595] Please remember your password!
|
||||
Generated account 0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
```
|
||||
|
||||
It is important to save the account address and the password somewhere secure. They will be used again later in this tutorial. Please note that the account address shown in the code snippets above and later in this tutorials are examples - those generated by followers of this tutorial will be different. The account generated above can be used as the main account throughout the remainder of this tutorial. However in order to demonstrate transactions between accounts it is also necessary to have a second account. A second account can be added to the same keystore by precisely repeating the previous steps, providing the same password.
|
||||
|
||||
## Step 2: Start Clef
|
||||
|
||||
The previous commands used Clef's `newaccount` function to add new key pairs to the keystore. Clef uses the private key(s) saved in the keystore is used to sign transactions. In order to do this, Clef needs to be started and left running while Geth is running simultaneously, so that the two programs can communicate between one another.
|
||||
|
||||
To start Clef, run the Clef executable passing as arguments the keystore file location, config directory location and a chain ID. The config directory was automatically created inside the `geth-tutorial` directory during the previous step. The [chain ID](https://chainlist.org/) is an integer that defines which Ethereum network to connect to. Ethereum mainnet has chain ID 1. In this tutorial Chain ID 5 is used which is that of the Goerli testnet. It is very important that this chain ID parameter is set to 5. The following command starts Clef on Goerli:
|
||||
|
||||
```shell
|
||||
clef --keystore geth-tutorial/keystore --configdir geth-tutorial/clef --chainid 5
|
||||
```
|
||||
|
||||
After running the command above, Clef requests the user to type “ok” to proceed. On typing "ok" and pressing enter, Clef returns the following to the terminal:
|
||||
|
||||
```terminal
|
||||
INFO [02-10|13:55:30.812] Using CLI as UI-channel
|
||||
INFO [02-10|13:55:30.946] Loaded 4byte database embeds=146,841 locals=0 local=./4byte-custom.json
|
||||
WARN [02-10|13:55:30.947] Failed to open master, rules disabled err="failed stat on geth-tutorial/clef/masterseed.json: stat geth-tutorial/clef/masterseed.json: no such file or directory"
|
||||
INFO [02-10|13:55:30.947] Starting signer chainid=5 keystore=geth-tutorial/keystore light-kdf=false advanced=false
|
||||
DEBUG[02-10|13:55:30.948] FS scan times list="133.35µs" set="5.692µs" diff="3.262µs"
|
||||
DEBUG[02-10|13:55:30.970] Ledger support enabled
|
||||
DEBUG[02-10|13:55:30.973] Trezor support enabled via HID
|
||||
DEBUG[02-10|13:55:30.976] Trezor support enabled via WebUSB
|
||||
INFO [02-10|13:55:30.978] Audit logs configured file=audit.log
|
||||
DEBUG[02-10|13:55:30.981] IPCs registered namespaces=account
|
||||
INFO [02-10|13:55:30.984] IPC endpoint opened url=geth-tutorial/clef/clef.ipc
|
||||
------- Signer info -------
|
||||
* intapi_version : 7.0.1
|
||||
* extapi_version : 6.1.0
|
||||
* extapi_http : n/a
|
||||
* extapi_ipc : geth-tutorial/clef/clef.ipc
|
||||
```
|
||||
|
||||
This result indicates that Clef is running. This terminal should be left running for the duration of this tutorial. If the tutorial is stopped and restarted later Clef must also be restarted by running the previous command.
|
||||
|
||||
## Step 3: Start Geth
|
||||
|
||||
Geth is the Ethereum client that will connect the computer to the Ethereum network. In this tutorial the network is Goerli, an Ethereum testnet. Testnets are used to test Ethereum client software and smart contracts in an environment where no real-world value is at risk. To start Geth, run the Geth executable file passing argument that define the data directory (where Geth should save blockchain data), signer (points Geth to Clef), the network ID and the sync mode. For this tutorial, snap sync is recommended (see [here](https://blog.ethereum.org/2021/03/03/geth-v1-10-0/) for reasons why). The final argument passed to Geth is the `--http` flag. This enables the http-rpc server that allows external programs to interact with Geth by sending it http requests. By default the http server is only exposed locally using port 8545: `localhost:8545`.
|
||||
|
||||
The following command should be run in a new terminal, separate to the one running Clef:
|
||||
|
||||
```shell
|
||||
geth --datadir geth-tutorial --signer=geth-tutorial/clef/clef.ipc --goerli --syncmode snap --http
|
||||
```
|
||||
|
||||
Running the above command starts Geth. The terminal should rapidly fill with status updates, starting with:
|
||||
|
||||
```terminal
|
||||
INFO [02-10|13:59:06.649] Starting Geth on goerli testnet...
|
||||
INFO [02-10|13:59:06.649] Dropping default light client cache provided=1024 updated=128
|
||||
INFO [02-10|13:59:06.652] Maximum peer count ETH=50 LES=0 total=50
|
||||
INFO [02-10|13:59:06.655] Using external signer url=geth-tutorial/clef/clef.ipc
|
||||
INFO [02-10|13:59:06.660] Set global gas cap cap=50,000,000
|
||||
INFO [02-10|13:59:06.661] Allocated cache and file handles database=/.../geth-tutorial/geth/chaindata cache=64.00MiB handles=5120
|
||||
INFO [02-10|13:59:06.855] Persisted trie from memory database nodes=361 size=51.17KiB time="643.54µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
|
||||
INFO [02-10|13:59:06.855] Initialised chain configuration config="{ChainID: 5 Homestead: 0 DAO: nil DAOSupport: true EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: 1561651, Muir Glacier: nil, Berlin: 4460644, London: 5062605, Arrow Glacier: nil, MergeFork: nil, Engine: clique}"
|
||||
INFO [02-10|13:59:06.862] Added trusted checkpoint block=5,799,935 hash=2de018..c32427
|
||||
INFO [02-10|13:59:06.863] Loaded most recent local header number=6,340,934 hash=483cf5..858315 td=9,321,576 age=2d9h29m
|
||||
INFO [02-10|13:59:06.867] Configured checkpoint oracle address=0x18CA0E045F0D772a851BC7e48357Bcaab0a0795D signers=5 threshold=2
|
||||
INFO [02-10|13:59:06.867] Gasprice oracle is ignoring threshold set threshold=2
|
||||
WARN [02-10|13:59:06.869] Unclean shutdown detected booted=2022-02-08T04:25:08+0100 age=2d9h33m
|
||||
INFO [02-10|13:59:06.870] Starting peer-to-peer node instance=Geth/v1.10.15-stable/darwin-amd64/go1.17.5
|
||||
INFO [02-10|13:59:06.995] New local node record seq=1,644,272,735,880 id=d4ffcd252d322a89 ip=127.0.0.1 udp=30303 tcp=30303
|
||||
INFO [02-10|13:59:06.996] Started P2P networking self=enode://4b80ebd341b5308f7a6b61d91aa0ea31bd5fc9e0a6a5483e59fd4ea84e0646b13ecd289e31e00821ccedece0bf4b9189c474371af7393093138f546ac23ef93e@127.0.0.1:30303
|
||||
INFO [02-10|13:59:06.997] IPC endpoint opened url=/.../geth-tutorial/geth.ipc
|
||||
INFO [02-10|13:59:06.998] HTTP server started endpoint=127.0.0.1:8545 prefix= cors= vhosts=localhost
|
||||
WARN [02-10|13:59:06.998] Light client mode is an experimental feature
|
||||
WARN [02-10|13:59:06.999] Failed to open wallet url=extapi://geth-tutorial/clef/cle.. err="operation not supported on external signers"
|
||||
INFO [02-10|13:59:08.793] Block synchronisation started
|
||||
```
|
||||
|
||||
This indicates that Geth has started up and is searching for peers to connect to. Once it finds peers it can request block headers from them, starting at the genesis block for the Goerli blockchain. Geth continues to download blocks sequentially, saving the data in files in `/go-ethereum/geth-tutorial/geth/chaindata/`. This is confirmed by the logs printed to the terminal. There should be a rapidly-growing sequence of logs in the terminal with the following syntax:
|
||||
|
||||
```terminal
|
||||
INFO [04-29][15:54:09.238] Looking for peers peercount=2 tried=0 static=0
|
||||
INFO [04-29][15:54:19.393] Imported new block headers count=2 elapsed=1.127ms number=996288 hash=09f1e3..718c47 age=13h9m5s
|
||||
INFO [04-29][15:54:19:656] Imported new block receipts count=698 elapsed=4.464ms number=994566 hash=56dc44..007c93 age=13h9m9s
|
||||
```
|
||||
|
||||
These logs indicate that Geth is running as expected. Sending an empty Curl request to the http server provides a quick way to confirm that this too has been started without any issues. In a third terminal, the following command can be run:
|
||||
|
||||
```shell
|
||||
curl http://localhost:8545
|
||||
```
|
||||
|
||||
If there is no error message reported to the terminal, everything is OK. Geth must be running in order for a user to interact with the Ethereum network. If this terminal is closed down then Geth must be restarted in a new terminal. Geth can be started and stopped easily, but it must be running for any interaction with Ethereum to take place. To shut down Geth, simply press `CTRL+C` in the Geth terminal. To start it again, run the previous command `geth --datadir <other commands>`.
|
||||
|
||||
{% include note.html content="Snap syncing Goerli will take some time and until the sync is finished you can't use the node to transfer funds. You can also try doing a [light sync](interface/les) which will be much quicker but depends on light servers being available to serve your node the data it needs." %}
|
||||
|
||||
## Step 4: Get Testnet Ether
|
||||
|
||||
In order to make some transactions, the user must fund their account with ether. On Ethereum mainnet, ether can only be obtained in three ways: 1) by receiving it as a reward for mining/validating; 2) receiving it in a transfer from another Ethereum user or contract; 3) receiving it from an exchange, 3) having paid for it with fiat money. On Ethereum testnets, the ether has no real world value so it 4) can be made freely available via faucets. Faucets allow users to request a transfer of testnet ether to their account.
|
||||
|
||||
The address generated by Clef in Step 1 can be pasted into the Paradigm Multifaucet faucet [here](https://fauceth.komputing.org/?chain=1115511). This requires a Twitter login as proof of personhood. The faucets adds ether to the given address on multiple testnets simultaneously, including Goerli. In the next steps Geth will be used to check that the ether has been sent to the given address and send some of it to the second address created earlier.
|
||||
|
||||
## Step 5: Interact with Geth
|
||||
|
||||
For interacting with the blockchain, Geth provides JSON-RPC APIs. [JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/) is a way to execute specific tasks by sending instructions to Geth in the form of [JSON](https://www.json.org/json-en.html) objects. RPC stands for "Remote Procedure Call" and it refers to the ability to send these JSON-encoded instructions from locations outside of those managed by Geth. It is possible to interact with Geth by sending these JSON encoded instructions directly over Geth's exposed http port using tools like Curl. However, this is somewhat user-unfriendly and error-prone, especially for more complex instructions. For this reason, there are a set of libraries built on top of JSON-RPC that provide a more user-friendly interface for interacting with Geth. One of the most widely used is Web3.js.
|
||||
|
||||
Geth provides a Javascript console that exposes the Web3.js API. This means that with Geth running in one terminal, a Javascript environment can be opened in another allowing the user to interact with Geth using Web3.js. There are three transport protocols that can be used to connect the Javascript environment to Geth:
|
||||
|
||||
- IPC (Inter-Process Communication): Provides unrestricted access to all APIs, but only works when the console is run on the same host as the geth node.
|
||||
- HTTP: By default provides access to the `eth`, `web3` and `net` method namespaces.
|
||||
|
||||
- Websocket: By default provides access to the `eth`, `web3` and `net` method namespaces.
|
||||
|
||||
This tutorial will use the HTTP option. Note that the terminals running Geth and Clef should both still be active. In a new (third) terminal, the following command can be run to start the console and connect it to Geth using the exposed http port:
|
||||
|
||||
```shell
|
||||
geth attach http://127.0.0.1:8545
|
||||
```
|
||||
|
||||
This command causes the terminal to hang because it is waiting for approval from Clef. Approving the request in the terminal running Clef will lead to the following welcome message being displayed in the Javascript console:
|
||||
|
||||
```terminal
|
||||
Welcome to the Geth JavaScript console!
|
||||
|
||||
instance: Geth/v1.10.15-stable/darwin-amd64/go1.17.5
|
||||
at block: 6354736 (Thu Feb 10 2022 14:01:46 GMT+0100 (WAT))
|
||||
modules: eth:1.0 net:1.0 rpc:1.0 web3:1.0
|
||||
|
||||
To exit, press ctrl-d or type exit
|
||||
```
|
||||
|
||||
The console is now active and connected to Geth. It can now be used to interact with the Ethereum (Goerli) network.
|
||||
|
||||
### List of accounts
|
||||
|
||||
In this tutorial, the accounts are managed using Clef. This means that requesting information about the accounts requires explicit approval in Clef, which should still be running in its own terminal. Earlier in this tutorial, two accounts were created using Clef. The following command will display the addresses of those two accounts and any others that might have been added to the keystore before or since.
|
||||
|
||||
```javascript
|
||||
eth.accounts;
|
||||
```
|
||||
|
||||
The console will hang, because Clef is waiting for approval. The following message will be displayed in the Clef terminal:
|
||||
|
||||
```terminal
|
||||
-------- List Account request--------------
|
||||
A request has been made to list all accounts.
|
||||
You can select which accounts the caller can see
|
||||
[x] 0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC
|
||||
URL: keystore:///.../geth-tutorial/keystore/UTC--2022-02-07T17-19-56.517538000Z--ca57f3b40b42fcce3c37b8d18adbca5260ca72ec
|
||||
[x] 0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
URL: keystore:///.../geth-tutorial/keystore/UTC--2022-02-10T12-46-45.265592000Z--ce8dba5e4157c2b284d8853afeeea259344c1653
|
||||
-------------------------------------------
|
||||
Request context:
|
||||
NA - ipc - NA
|
||||
|
||||
Additional HTTP header data, provided by the external caller:
|
||||
User-Agent: ""
|
||||
Origin: ""
|
||||
Approve? [y/N]:
|
||||
|
||||
```
|
||||
|
||||
Entering `y` approves the request from the console. In the terminal running the Javascript console, the account addresses are now displayed:
|
||||
|
||||
```terminal
|
||||
["0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec", "0xce8dba5e4157c2b284d8853afeeea259344c1653"]
|
||||
```
|
||||
|
||||
It is also possible for this request to time out if the Clef approval took too long - in this case simply repeat the request and approval.
|
||||
|
||||
### Checking account balance.
|
||||
|
||||
Having confirmed that the two addresses created earlier are indeed in the keystore and accessible through the Javascript console, it is possible to retrieve information about how much ether they own. The Goerli faucet should have sent 1 ETH to the address provided, meaning that the balance of one of the accounts should be 1 ether and the other should be 0. The following command displays the account balance in the console:
|
||||
|
||||
```javascript
|
||||
web3.fromWei(eth.getBalance('0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC'), 'ether');
|
||||
```
|
||||
|
||||
There are actually two instructions sent in the above command. The inner one is the `getBalance` function from the `eth` namespace. This takes the account address as its only argument. By default, this returns the account balance in units of Wei. There are 10<sup>18</sup> Wei to one ether. To present the result in units of ether, `getBalance` is wrapped in the `fromWei` function from the `web3` namespace. Running this command should provide the following result (for the account that received faucet funds):
|
||||
|
||||
```terminal
|
||||
1
|
||||
```
|
||||
|
||||
Repeating the command for the other account should yield:
|
||||
|
||||
```terminal
|
||||
0
|
||||
```
|
||||
|
||||
### Send ether to another account
|
||||
|
||||
The command `eth.sendTransaction` can be used to send some ether from one address to another. This command takes three arguments: `from`, `to` and `value`. These define the sender and recipient addresses (as strings) and the amount of Wei to transfer. It is far less error prone to enter the transaction value in units of ether rather than Wei, so the value field can take the return value from the `toWei` function. The following command, run in the Javascript console, sends 0.1 ether from one of the accounts in the Clef keystore to the other. Note that the addresses here are examples - the user must replace the address in the `from` field with the address currently owning 1 ether, and the address in the `to` field with the address currently holding 0 ether.
|
||||
|
||||
```javascript
|
||||
eth.sendTransaction({
|
||||
from: '0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec',
|
||||
to: '0xce8dba5e4157c2b284d8853afeeea259344c1653',
|
||||
value: web3.toWei(0.1, 'ether')
|
||||
});
|
||||
```
|
||||
|
||||
Note that submitting this transaction requires approval in Clef. In the Clef terminal, Clef will prompt for approval and request the account password. If the password is correctly entered, Geth proceeds with the transaction. The transaction request summary is presented by Clef in the Clef terminal. This is an opportunity for the sender to review the details and ensure they are correct.
|
||||
|
||||
```terminal
|
||||
--------- Transaction request-------------
|
||||
to: 0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
from: 0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC [chksum ok]
|
||||
value: 10000000000000000 wei
|
||||
gas: 0x5208 (21000)
|
||||
maxFeePerGas: 2425000057 wei
|
||||
maxPriorityFeePerGas: 2424999967 wei
|
||||
nonce: 0x3 (3)
|
||||
chainid: 0x5
|
||||
Accesslist
|
||||
|
||||
Request context:
|
||||
NA - ipc - NA
|
||||
|
||||
Additional HTTP header data, provided by the external caller:
|
||||
User-Agent: ""
|
||||
Origin: ""
|
||||
-------------------------------------------
|
||||
Approve? [y/N]:
|
||||
|
||||
Please enter the password for account 0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC
|
||||
|
||||
```
|
||||
|
||||
After approving the transaction, the following confirmation screen in displayed in the Clef terminal:
|
||||
|
||||
```terminal
|
||||
-----------------------
|
||||
Transaction signed:
|
||||
{
|
||||
"type": "0x2",
|
||||
"nonce": "0x3",
|
||||
"gasPrice": null,
|
||||
"maxPriorityFeePerGas": "0x908a901f",
|
||||
"maxFeePerGas": "0x908a9079",
|
||||
"gas": "0x5208",
|
||||
"value": "0x2386f26fc10000",
|
||||
"input": "0x",
|
||||
"v": "0x0",
|
||||
"r": "0x66e5d23ad156e04363e68b986d3a09e879f7fe6c84993cef800bc3b7ba8af072",
|
||||
"s": "0x647ff82be943ea4738600c831c4a19879f212eb77e32896c05055174045da1bc",
|
||||
"to": "0xce8dba5e4157c2b284d8853afeeea259344c1653",
|
||||
"chainId": "0x5",
|
||||
"accessList": [],
|
||||
"hash": "0x99d489d0bd984915fd370b307c2d39320860950666aac3f261921113ae4f95bb"
|
||||
}
|
||||
```
|
||||
|
||||
In the Javascript console, the transaction hash is displayed. This will be used in the next section to retrieve the transaction details.
|
||||
|
||||
```terminal
|
||||
"0x99d489d0bd984915fd370b307c2d39320860950666aac3f261921113ae4f95bb"
|
||||
```
|
||||
|
||||
It is also advised to check the account balances using Geth by repeating the instructions from earlier. At this point in the tutorial, the two accounts in the Clef keystore should have balances just below 0.9 ether (because 0.1 ether has been transferred out and some small amount paid in transaction gas) and 0.1 ether.
|
||||
|
||||
### Checking the transaction hash
|
||||
|
||||
The transaction hash is a unique identifier for this specific transaction that can be used later to retrieve the transaction details. For example, the transaction details can be viewed by pasting this hash into the [Goerli block explorer](https://goerli.etherscan.io/). The same information can also be retrieved directly from the Geth node. The hash returned in the previous step can be provided as an argument to `eth.getTransaction` to return the transaction information:
|
||||
|
||||
```javascript
|
||||
eth.getTransaction('0x99d489d0bd984915fd370b307c2d39320860950666aac3f261921113ae4f95bb');
|
||||
```
|
||||
|
||||
This returns the following response (although the actual values for each field will vary because they are specific to each transaction):
|
||||
|
||||
```terminal
|
||||
{
|
||||
accessList: [],
|
||||
blockHash: "0x1c5d3f8dd997b302935391b57dc3e4fffd1fa2088ef2836d51f844f993eb39c4",
|
||||
blockNumber: 6355150,
|
||||
chainId: "0x5",
|
||||
from: "0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec",
|
||||
gas: 21000,
|
||||
gasPrice: 2425000023,
|
||||
hash: "0x99d489d0bd984915fd370b307c2d39320860950666aac3f261921113ae4f95bb",
|
||||
input: "0x",
|
||||
maxFeePerGas: 2425000057,
|
||||
maxPriorityFeePerGas: 2424999967,
|
||||
nonce: 3,
|
||||
r: "0x66e5d23ad156e04363e68b986d3a09e879f7fe6c84993cef800bc3b7ba8af072",
|
||||
s: "0x647ff82be943ea4738600c831c4a19879f212eb77e32896c05055174045da1bc",
|
||||
to: "0xce8dba5e4157c2b284d8853afeeea259344c1653",
|
||||
transactionIndex: 630,
|
||||
type: "0x2",
|
||||
v: "0x0",
|
||||
value: 10000000000000000
|
||||
}
|
||||
```
|
||||
|
||||
## Using Curl
|
||||
|
||||
Up to this point this tutorial has interacted with Geth using the convenience library Web3.js. This library enables the user to send instructions to Geth using a more user-friendly interface compared to sending raw JSON objects. However, it is also possible for the user to send these JSON objects directly to Geth's exposed HTTP port. Curl is a command line tool that sends HTTP requests. This part of the tutorial demonstrates how to check account balances and send a transaction using Curl.
|
||||
|
||||
### Checking account balance
|
||||
|
||||
The command below returns the balance of the given account. This is a HTTP POST request to the local port 8545. The `-H` flag is for header information. It is used here to define the format of the incoming payload, which is JSON. The `--data` flag defines the content of the payload, which is a JSON object. That JSON object contains four fields: `jsonrpc` defines the spec version for the JSON-RPC API, `method` is the specific function being invoked, `params` are the function
|
||||
arguments, and `id` is used for ordering transactions. The two arguments passed to `eth_getBalance` are the account address whose balance to check and the block to query (here `latest` is used to check the balance in the most recently mined block).
|
||||
|
||||
```shell
|
||||
curl -X POST http://127.0.0.1:8545 \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec","latest"], "id":1}'
|
||||
```
|
||||
|
||||
A successful call will return a response like the one below:
|
||||
|
||||
```terminal
|
||||
{"jsonrpc":"2.0","id":1,"result":"0xc7d54951f87f7c0"}
|
||||
```
|
||||
|
||||
The balance is in the `result` field in the returned JSON object. However, it is denominated in Wei and presented as a hexadecimal string. There are many options for converting this value to a decimal in units of ether, for example by opening a Python console and running:
|
||||
|
||||
```python
|
||||
0xc7d54951f87f7c0 / 1e18
|
||||
```
|
||||
|
||||
This returns the balance in ether:
|
||||
|
||||
```terminal
|
||||
0.8999684999998321
|
||||
```
|
||||
|
||||
### Checking the account list
|
||||
|
||||
The curl command below returns the list of all accounts.
|
||||
|
||||
```shell
|
||||
curl -X POST http://127.0.0.1:8545 \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0", "method":"eth_accounts","params":[], "id":1}'
|
||||
```
|
||||
|
||||
This requires approval in Clef. Once approved, the following information is returned to the terminal:
|
||||
|
||||
```terminal
|
||||
{"jsonrpc":"2.0","id":1,"result":["0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec"]}
|
||||
```
|
||||
|
||||
### Sending Transactions
|
||||
|
||||
Sending a transaction between accounts can also be achieved using Curl. Notice that the value of the transaction is a hexadecimal string in units of Wei. To transfer 0.1 ether, it is first necessary to convert this to Wei by multiplying by 10<sup>18</sup> then converting to hex. 0.1 ether is `"0x16345785d8a0000"` in hex. As before, update the `to` and `from` fields with the addresses in the Clef keystore.
|
||||
|
||||
```shell
|
||||
curl -X POST http://127.0.0.1:8545 \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0", "method":"eth_sendTransaction", "params":[{"from": "0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec","to": "0xce8dba5e4157c2b284d8853afeeea259344c1653","value": "0x16345785d8a0000"}], "id":1}'
|
||||
```
|
||||
|
||||
This requires approval in Clef. Once the password for the sender account has been provided, Clef will return a summary of the transaction details and the terminal that made the Curl request will display a response containing the transaction hash.
|
||||
|
||||
```terminal
|
||||
{"jsonrpc":"2.0","id":5,"result":"0xac8b347d70a82805edb85fc136fc2c4e77d31677c2f9e4e7950e0342f0dc7e7c"}
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
This tutorial has demonstrated how to generate accounts using Clef, fund them with testnet ether and use those accounts to interact with Ethereum (Goerli) through a Geth node. Checking account balances, sending transactions and retrieving transaction details were explained using the web3.js library via the Geth console and using the JSON-RPC directly using Curl. For more detailed information about Clef, please see [the Clef docs](/docs/tools/Clef/Tutorial).
|
|
@ -5,21 +5,21 @@ description: Overview of the hardware needed to run an Ethereum node
|
|||
|
||||
The hardware requirements for running a Geth node depend upon the node configuration and can change over time as upgrades to the network are implemented. Ethereum nodes can be run on low power, resource-constrained devices such as Raspberry Pi's. Prebuilt, dedicated staking machines are available from several companies - these might be good choices for users who want plug-and-play hardware specifically designed for Ethereum. However, many users will choose to run nodes on laptop or desktop computers.
|
||||
|
||||
## Processor
|
||||
## Processor {#processor}
|
||||
|
||||
It is preferable to use a quad-core (or dual-core hyperthreaded) CPU. Geth is released for a wide range of architectures.
|
||||
|
||||
## Memory
|
||||
## Memory {#memory}
|
||||
|
||||
It is recommended to use at least 16GB RAM.
|
||||
|
||||
## Disk space
|
||||
## Disk space {#disk-space}
|
||||
|
||||
Disk space is usually the primary bottleneck for node operators. At the time of writing (September 2022) a 2TB SSD is recommended for a full node running Geth and a consensus client. Geth itself requires >650GB of disk space for a snap-synced full node and, with the default cache size, grows about 14GB/week. Pruning brings the total storage back down to the original 650GB.
|
||||
Archive nodes require additional space. A "full" archive node that keeps all state back to genesis requires more than 12TB of space. Partial archive nodes can also be created by turning off the garbage collector after some initial sync - the storage requirement depends how much state is saved.
|
||||
|
||||
As well as storage capacity, Geth nodes rely on fast read and write operations. This means HDDs and cheaper HDDS can sometimes struggle to sync the blockchain. A list of SSD models that users report being able and unable to sync Geth is available in this [Github Gist](https://gist.github.com/yorickdowne/f3a3e79a573bf35767cd002cc977b038). Please note that the list has _not_ been verified by the Geth team.
|
||||
|
||||
## Bandwidth
|
||||
## Bandwidth {#bandwidth}
|
||||
|
||||
It is important to have a stable and reliable internet connection, especially for running a validator because downtime can result in missed rewards or penalties. It is recommended to have at least 25Mbps download speed to run a node. Running a node also requires a lot of data to be uploaded and downloaded so it is better to use an ISP that does not have a capped data allowance.
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
---
|
||||
title: Getting Started with Geth
|
||||
description: Instructions for getting up and running with Geth
|
||||
title: Getting started with Geth
|
||||
description: Guide to getting up and running with Geth using Clef.
|
||||
---
|
||||
|
||||
This page explains how to set up Geth and execute some basic tasks using the command line tools. In order to use Geth, the software must first be installed. There are several ways Geth can be installed depending on the operating system and the user's choice of installation method, for example using a package manager, container or building from source. Instructions for installing Geth can be found on the ["Install and Build"](/docs/getting_started/Installing-Geth) pages. Geth also needs to be connected to a consensus client in order to function as an Ethereum node. The tutorial on this page assumes Geth and a consensus client have been installed successfully and that a firewall has been configured to block external traffic to the JSON-RPC port `8545` see [Security](/docs/fundamentals/security).
|
||||
This page explains how to set up Geth and execute some basic tasks using the command line tools. In order to use Geth, the software must first be installed. There are several ways Geth can be installed depending on the operating system and the user's choice of installation method, for example using a package manager, container or building from source. Instructions for installing Geth can be found on the ["Install and Build"](/docs/getting_started/Installing-Geth) pages.
|
||||
|
||||
This page provides step-by-step instructions covering the fundamentals of using Geth. This includes generating accounts, joining an Ethereum network, syncing the blockchain and sending ether between accounts. This page uses Geth's built in account management tool. This is the simplest method for creating and accessing accounts in Geth, is sufficiently secure for many purposes and provides a good entry point for understanding some of the basic Geth workflows. However, Geth also comes bundled with an external signer and account management tool called [Clef](/tools/Clef/introduction). It is best practise to use Clef instead of Geth's built-in account management tools because Clef is decoupled from Geth and can be run in a separate, secure environment. This page should be used as an initial entry point into basic Geth and readers should plan to advance from this page to [Getting started with Geth and Clef](/docs/getting_started/getting-started-with-clef). Eventually, Clef is intended to replace Geth's built-in account management tools.
|
||||
Geth also needs to be connected to a [consensus client](docs/getting-started/consensus-clients.md) in order to function as an Ethereum node. The tutorial on this page assumes Geth and a consensus client have been installed successfully and that a firewall has been configured to block external traffic to the JSON-RPC port `8545` see [Security](/docs/fundamentals/security).
|
||||
|
||||
## Prerequisites
|
||||
This page provides step-by-step instructions covering the fundamentals of using Geth. This includes generating accounts, joining an Ethereum network, syncing the blockchain and sending ether between accounts. This tutorial uses [Clef](/docs/tools/Clef/Tutorial). Clef is an account management tool external to Geth itself that allows users to sign transactions. It is developed and maintained by the Geth team.
|
||||
|
||||
In order to get the most value from the tutorials on this page, the following skills are
|
||||
necessary:
|
||||
## Prerequisites {#prerequisites}
|
||||
|
||||
In order to get the most value from the tutorials on this page, the following skills are necessary:
|
||||
|
||||
- Experience using the command line
|
||||
- Basic knowledge about Ethereum and testnets
|
||||
|
@ -20,75 +21,116 @@ necessary:
|
|||
Users that need to revisit these fundamentals can find helpful resources relating to the command line [here](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line), Ethereum and its testnets [here](https://ethereum.org/en/developers/tutorials/), http [here](https://developer.mozilla.org/en-US/docs/Web/HTTP) and Javascript [here](https://www.javascript.com/learn). Information on node architecture can be found [here](/docs/fundamentals/node-architecture) and our guide for configuring Geth to connect to a
|
||||
consensus client is [here](/docs/getting_started/consensus-clients).
|
||||
|
||||
{% include note.html content="If Geth was installed from source on Linux, `make` saves the binaries for Geth and the associated tools in `/build/bin`. To run these programs it is convenient to move them to the top level project directory (e.g. running `mv ./build/bin/* ./`) from `/go-ethereum`. Then `./` must be prepended to the commands in the code snippets in order to execute a particular program, e.g. `./geth` instead of simply `geth`. If the executables are not
|
||||
moved then either navigate to the `bin` directory to run them (e.g. `cd ./build/bin` and `./geth`) or provide their path (e.g. `./build/bin/geth`). These instructions can be ignored for other installations." %}
|
||||
{% include note.html content="If Geth was installed from source on Linux, `make` saves the binaries for Geth and the associated tools in `/build/bin`. To run these programs it is convenient to move them to the top level project directory (e.g. running `mv ./build/bin/* ./`) from `/go-ethereum`. Then `./` must be prepended to the commands in the code snippets in order to execute a particular program, e.g. `./geth` instead of simply `geth`. If the executables are not moved then either navigate to the `bin` directory to run them (e.g. `cd ./build/bin` and `./geth`) or provide their path (e.g. `./build/bin/geth`). These instructions can be ignored for other installations." %}
|
||||
|
||||
## Background
|
||||
## Background {#background}
|
||||
|
||||
Geth is an Ethereum client written in Go. This means running Geth turns a computer into an Ethereum node. Ethereum is a peer-to-peer network where information is shared directly between nodes rather than being managed by a central server. Every 12 seconds one node is randomly selected to generate a new block
|
||||
containing a list of transactions that nodes receiving the block should execute. This "block proposer" node sends the new block to its peers. On receiving a new block, each node checks that it is valid and adds it to their database. The sequence of discrete blocks is called a "blockchain".
|
||||
Geth is an Ethereum client written in Go. This means running Geth turns a computer into an Ethereum node. Ethereum is a peer-to-peer network where information is shared directly between nodes rather than being managed by a central server. Every 12 seconds one node is randomly selected to generate a new block containing a list of transactions that nodes receiving the block should execute. This "block proposer" node sends the new block to its peers. On receiving a new block, each node checks that it is valid and adds it to their database. The sequence of discrete blocks is called a "blockchain".
|
||||
|
||||
The information provided in each block is used by Geth to update its "state" - the ether balance of each account on Ethereum and the data stored by each smart contract. There are two types of account: externally-owned accounts (EOAs) and contract accounts. Contract accounts execute contract code when they receive transactions. EOAs are accounts that users manage locally in order to sign and submit transactions. Each EOA is a public-private key pair, where the public key is used to derive a unique address for the user and the private key is used to protect the account and securely sign messages. Therefore, in order to use Ethereum,
|
||||
it is first necessary to generate an EOA (hereafter, "account"). This tutorial will guide the user through creating an account, funding it with ether and sending some to another address.
|
||||
The information provided in each block is used by Geth to update its "state" - the ether balance of each account on Ethereum and the data stored by each smart contract. There are two types of account: externally-owned accounts (EOAs) and contract accounts. Contract accounts execute contract code when they receive transactions. EOAs are accounts that users manage locally in order to sign and submit transactions. Each EOA is a public-private key pair, where the public key is used to derive a unique address for the user and the private key is used to protect the account and securely sign messages. Therefore, in order to use Ethereum, it is first necessary to generate an EOA (hereafter, "account"). This tutorial will guide the user through creating an account, funding it with ether and sending some to another address.
|
||||
|
||||
Read more about Ethereum accounts [here](https://ethereum.org/en/developers/docs/accounts/).
|
||||
|
||||
## Step 1: Generating accounts
|
||||
## Step 1: Generating accounts {#generating-accounts}
|
||||
|
||||
To generate a new account in Geth:
|
||||
There are several methods for generating accounts in Geth. This tutorial demonstrates how to generate accounts using Clef, as this is considered best practice, largely because it decouples the users' key management from Geth, making it more modular and flexible. It can also be run from secure USB sticks or virtual machines, offering security benefits. For convenience, this tutorial will execute Clef on the same computer that will also run Geth, although more secure options are available (see [here](https://github.com/ethereum/go-ethereum/blob/master/cmd/clef/docs/setup.md)).
|
||||
|
||||
```sh
|
||||
geth account new
|
||||
```
|
||||
|
||||
This returns a prompt for a password. Once provided, a new account will be created and added to the default keystore (`/datadir/keystore`). A custom keystore can also be provided by passing `--keystore <path>`. In this tutorial the keys will be stored in a new data directory `geth-tutorial`. Create that directory, then run:
|
||||
|
||||
```sh
|
||||
geth account new --keystore geth-tutorial/keystore
|
||||
```
|
||||
|
||||
The following will be returned to the console, confirming the new account has been created and added to the keystore.
|
||||
|
||||
```terminal
|
||||
Your new account is locked with a password. Please give a password. Do not forget this password.
|
||||
Password:
|
||||
Repeat password:
|
||||
|
||||
Your new key was generated
|
||||
|
||||
Public address of the key: 0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC
|
||||
Path of the secret key file: /home/go-ethereum/geth-tutorial/keystore/UTC--2022-07-25T08-27-59.433905560Z--ca57F3b40B42FCce3c37B8D18aDBca5260ca72EC
|
||||
|
||||
- You can share your public address with anyone. Others need it to interact with you.
|
||||
- You must NEVER share the secret key with anyone! The key controls access to your funds!
|
||||
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
|
||||
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
|
||||
```
|
||||
|
||||
It is important to save the account address and the password somewhere secure. They will be used again later in this tutorial. Please note that the account address shown in the code snippets above and later in this tutorials are examples - those generated by followers of this tutorial will be different. The account generated above can be used as the main account throughout the remainder of this tutorial. However in order to demonstrate transactions between accounts it is
|
||||
also necessary to have a second account. A second account can be added to the same keystore by precisely repeating the previous steps, providing the same password.
|
||||
|
||||
Notice that the path to the secret key includes a long filename that starts `UTC--`. This is the name of the file that contains the keys for the new account. It is **extremely important** that this file stays secure because it contains the secret key used to control access to any funds associated with the account. The file should be backed up securely along with the password used to encrypt it. If the file or the password is lost, then so is access to the funds in the account. If someone else gains access to the keyfile and password, they have access to any assets in the account.
|
||||
|
||||
## Step 2: Start Geth
|
||||
|
||||
Geth is the Ethereum client that will connect the computer to the Ethereum network. In this tutorial the network is Goerli, an Ethereum testnet. Testnets are used to test Ethereum client software and smart contracts in an environment where no real-world value is at risk. To start Geth, run the Geth executable file passing argument that define the data directory (where Geth should save blockchain data), the network ID and the sync mode. For this tutorial, snap sync is recommended
|
||||
(see [here](https://blog.ethereum.org/2021/03/03/geth-v1-10-0/) for reasons why). The following command should be run in the terminal:
|
||||
An account is a pair of keys (public and private). Clef needs to know where to save these keys to so that they can be retrieved later. This information is passed to Clef as an argument. This is achieved using the following command:
|
||||
|
||||
```shell
|
||||
geth --datadir geth-tutorial --goerli --syncmode snap
|
||||
clef newaccount --keystore geth-tutorial/keystore
|
||||
```
|
||||
|
||||
Running the above command starts Geth. The terminal should rapidly fill with status updates that look like the following:
|
||||
The specific function from Clef that generates new accounts is `newaccount` and it accepts a parameter, `--keystore`, that tells it where to store the newly generated keys. In this example the keystore location is a new directory that will be created automatically: `geth-tutorial/keystore`.
|
||||
Clef will return the following result in the terminal:
|
||||
|
||||
```terminal
|
||||
INFO [02-10|13:59:06.649] Starting Geth on goerli testnet...
|
||||
INFO [02-10|13:59:06.649] Dropping default light client cache provided=1024 updated=128
|
||||
WARNING!
|
||||
|
||||
Clef is an account management tool. It may, like any software, contain bugs.
|
||||
|
||||
Please take care to
|
||||
- backup your keystore files,
|
||||
- verify that the keystore(s) can be opened with your password.
|
||||
|
||||
Clef is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
Enter 'ok' to proceed:
|
||||
>
|
||||
```
|
||||
|
||||
This is important information. The `geth-tutorial/keystore` directory will soon contain a secret key that can be used to access any funds held in the new account. If it is compromised, the funds can be stolen. If it is lost, there is no way to retrieve the funds. This tutorial will only use dummy funds with no real world value, but when these steps are repeated on Ethereum mainnet is critical that the keystore is kept secure and backed up.
|
||||
|
||||
Typing `ok` into the terminal and pressing `enter` causes Clef to prompt for a password. Clef requires a password that is at least 10 characters long, and best practice would be to use a combination of numbers, characters and special characters. Entering a suitable password and pressing `enter` returns the following result to the terminal:
|
||||
|
||||
```terminal
|
||||
-----------------------
|
||||
DEBUG[02-10|13:46:46.436] FS scan times list="92.081µs" set="12.629µs" diff="2.129µs"
|
||||
INFO [02-10|13:46:46.592] Your new key was generated address=0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
WARN [02-10|13:46:46.595] Please backup your key file! path=keystore:///.../geth-tutorial/keystore/UTC--2022-02-07T17-19-56.517538000Z--ca57f3b40b42fcce3c37b8d18adbca5260ca72ec
|
||||
WARN [02-10|13:46:46.595] Please remember your password!
|
||||
Generated account 0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
```
|
||||
|
||||
It is important to save the account address and the password somewhere secure. They will be used again later in this tutorial. Please note that the account address shown in the code snippets above and later in this tutorials are examples - those generated by followers of this tutorial will be different. The account generated above can be used as the main account throughout the remainder of this tutorial. However in order to demonstrate transactions between accounts it is also necessary to have a second account. A second account can be added to the same keystore by precisely repeating the previous steps, providing the same password.
|
||||
|
||||
## Step 2: Start Clef {#start-clef}
|
||||
|
||||
The previous commands used Clef's `newaccount` function to add new key pairs to the keystore. Clef uses the private key(s) saved in the keystore is used to sign transactions. In order to do this, Clef needs to be started and left running while Geth is running simultaneously, so that the two programs can communicate between one another.
|
||||
|
||||
To start Clef, run the Clef executable passing as arguments the keystore file location, config directory location and a chain ID. The config directory was automatically created inside the `geth-tutorial` directory during the previous step. The [chain ID](https://chainlist.org/) is an integer that defines which Ethereum network to connect to. Ethereum mainnet has chain ID 1. In this tutorial Chain ID 11155111 is used which is that of the Sepolia testnet. It is very important that this chain ID parameter is set to 11155111 - Clef uses the chain ID to sign messages so it must be correct. The following command starts Clef on Sepolia:
|
||||
|
||||
```shell
|
||||
clef --keystore geth-tutorial/keystore --configdir geth-tutorial/clef --chainid 11155111
|
||||
```
|
||||
|
||||
After running the command above, Clef requests the user to type “ok” to proceed. On typing "ok" and pressing enter, Clef returns the following to the terminal:
|
||||
|
||||
```terminal
|
||||
INFO [02-10|13:55:30.812] Using CLI as UI-channel
|
||||
INFO [02-10|13:55:30.946] Loaded 4byte database embeds=146,841 locals=0 local=./4byte-custom.json
|
||||
WARN [02-10|13:55:30.947] Failed to open master, rules disabled err="failed stat on geth-tutorial/clef/masterseed.json: stat geth-tutorial/clef/masterseed.json: no such file or directory"
|
||||
INFO [02-10|13:55:30.947] Starting signer chainid=5 keystore=geth-tutorial/keystore light-kdf=false advanced=false
|
||||
DEBUG[02-10|13:55:30.948] FS scan times list="133.35µs" set="5.692µs" diff="3.262µs"
|
||||
DEBUG[02-10|13:55:30.970] Ledger support enabled
|
||||
DEBUG[02-10|13:55:30.973] Trezor support enabled via HID
|
||||
DEBUG[02-10|13:55:30.976] Trezor support enabled via WebUSB
|
||||
INFO [02-10|13:55:30.978] Audit logs configured file=audit.log
|
||||
DEBUG[02-10|13:55:30.981] IPCs registered namespaces=account
|
||||
INFO [02-10|13:55:30.984] IPC endpoint opened url=geth-tutorial/clef/clef.ipc
|
||||
------- Signer info -------
|
||||
* intapi_version : 7.0.1
|
||||
* extapi_version : 6.1.0
|
||||
* extapi_http : n/a
|
||||
* extapi_ipc : geth-tutorial/clef/clef.ipc
|
||||
```
|
||||
|
||||
This result indicates that Clef is running. This terminal should be left running for the duration of this tutorial. If the tutorial is stopped and restarted later Clef must also be restarted by running the previous command.
|
||||
|
||||
## Step 3: Start Geth {#start-geth}
|
||||
|
||||
Geth is the Ethereum client that will connect the computer to the Ethereum network. In this tutorial the network is Sepolia, an Ethereum testnet. Testnets are used to test Ethereum client software and smart contracts in an environment where no real-world value is at risk. To start Geth, run the Geth executable file passing argument that define the data directory (where Geth should save blockchain data), signer (points Geth to Clef), the network ID and the sync mode. For this tutorial, snap sync is recommended (see [here](https://blog.ethereum.org/2021/03/03/geth-v1-10-0/) for reasons why). The final argument passed to Geth is the `--http` flag. This enables the http-rpc server that allows external programs to interact with Geth by sending it http requests. By default the http server is only exposed locally using port 8545: `localhost:8545`. It is also necessary to authorize some traffic for the consensus client which is done using `--authrpc` and also to set up a JWT secret token in a known location, using `--jwt-secret`.
|
||||
|
||||
The following command should be run in a new terminal, separate to the one running Clef:
|
||||
|
||||
```shell
|
||||
geth --sepolia --datadir geth-tutorial --authrpc.addr localhost --authrpc.port 8551 --authrpc.vhosts localhost --authrpc.jwtsecret geth-tutorial/jwtsecret --http --http.api eth,net --signer=geth-tutorial/clef/clef.ipc --http
|
||||
```
|
||||
|
||||
Running the above command starts Geth. Geth will not sync the blockchain correctly unless there is also a consensus client that can pass Geth a valid head to sync up to. In a separate terminal, start a consensus client. Once the consensus client gets in sync, Geth will start to sync too.
|
||||
|
||||
The terminal should rapidly fill with status updates that look similar to those below. To check the meaning of the logs, refer to the [logs page](docs/fundamentals/logs.md).
|
||||
|
||||
```terminal
|
||||
INFO [02-10|13:59:06.649] Starting Geth on sepolia testnet...
|
||||
INFO [02-10|13:59:06.652] Maximum peer count ETH=50 LES=0 total=50
|
||||
INFO [02-10|13:59:06.655] Using external signer url=geth-tutorial/clef/clef.ipc
|
||||
INFO [02-10|13:59:06.660] Set global gas cap cap=50,000,000
|
||||
INFO [02-10|13:59:06.661] Allocated cache and file handles database=/.../geth-tutorial/geth/chaindata cache=64.00MiB handles=5120
|
||||
INFO [02-10|13:59:06.855] Persisted trie from memory database nodes=361 size=51.17KiB time="643.54µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
|
||||
INFO [02-10|13:59:06.855] Initialised chain configuration config="{ChainID: 5 Homestead: 0 DAO: nil DAOSupport: true EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: 1561651, Muir Glacier: nil, Berlin: 4460644, London: 5062605, Arrow Glacier: nil, MergeFork: nil, Engine: clique}"
|
||||
INFO [02-10|13:59:06.855] Initialised chain configuration config="{ChainID: 11155111 Homestead: 0 DAO: nil DAOSupport: true EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: 1561651, Muir Glacier: nil, Berlin: 4460644, London: 5062605, Arrow Glacier: nil, MergeFork: nil, Engine: clique}"
|
||||
INFO [02-10|13:59:06.862] Added trusted checkpoint block=5,799,935 hash=2de018..c32427
|
||||
INFO [02-10|13:59:06.863] Loaded most recent local header number=6,340,934 hash=483cf5..858315 td=9,321,576 age=2d9h29m
|
||||
INFO [02-10|13:59:06.867] Configured checkpoint oracle address=0x18CA0E045F0D772a851BC7e48357Bcaab0a0795D signers=5 threshold=2
|
||||
|
@ -98,12 +140,10 @@ INFO [02-10|13:59:06.870] Starting peer-to-peer node instance=Geth
|
|||
INFO [02-10|13:59:06.995] New local node record seq=1,644,272,735,880 id=d4ffcd252d322a89 ip=127.0.0.1 udp=30303 tcp=30303
|
||||
INFO [02-10|13:59:06.996] Started P2P networking self=enode://4b80ebd341b5308f7a6b61d91aa0ea31bd5fc9e0a6a5483e59fd4ea84e0646b13ecd289e31e00821ccedece0bf4b9189c474371af7393093138f546ac23ef93e@127.0.0.1:30303
|
||||
INFO [02-10|13:59:06.997] IPC endpoint opened url=/.../geth-tutorial/geth.ipc
|
||||
WARN [02-10|13:59:06.998] Light client mode is an experimental feature
|
||||
INFO [02-10|13:59:08.793] Block synchronisation started
|
||||
INFO [02-10|13:59:06.998] HTTP server started endpoint=127.0.0.1:8545 prefix= cors= vhosts=localhost
|
||||
```
|
||||
|
||||
This indicates that Geth has started up and is searching for peers to connect to. Once it finds peers it can request block headers from them, starting at the genesis block for the Goerli blockchain. Geth continues to download blocks sequentially, saving the data in files in `/go-ethereum/geth-tutorial/geth/chaindata/`.
|
||||
This is confirmed by the logs printed to the terminal. There should be a rapidly-growing sequence of logs in the terminal with the following syntax:
|
||||
By default, Geth uses snap-sync which download blocks sequentially from a relatively recent block, not the genesis block. It saves the data in files in `/go-ethereum/geth-tutorial/geth/chaindata/`. One the sequence of headers has been verified, Geth downloads the block bodies and state data before starting the "state healing" phase to update the state for newly arriving data. This is confirmed by the logs printed to the terminal. There should be a rapidly-growing sequence of logs in the terminal with the following syntax:
|
||||
|
||||
```terminal
|
||||
INFO [04-29][15:54:09.238] Looking for peers peercount=2 tried=0 static=0
|
||||
|
@ -111,87 +151,119 @@ INFO [04-29][15:54:19.393] Imported new block headers count=2 elapsed=1.127ms
|
|||
INFO [04-29][15:54:19:656] Imported new block receipts count=698 elapsed=4.464ms number=994566 hash=56dc44..007c93 age=13h9m9s
|
||||
```
|
||||
|
||||
These logs indicate that Geth is running as expected.
|
||||
This message will be displayed periodically until state healing has finished:
|
||||
|
||||
If there is no error message reported to the terminal, everything is OK. Geth must be running in order for a user to interact with the Ethereum network. If this terminal is closed down then Geth must be restarted again. Geth can be started and stopped easily, but it must be running for any interaction with Ethereum to take place. To shut down Geth, simply press `CTRL+C` in the Geth terminal. To start it again, run the previous command `geth --datadir <other commands>`.
|
||||
```
|
||||
INFO [10-20|20:20:09.510] State heal in progress accounts=313,309@17.95MiB slots=363,525@28.77MiB codes=7222@50.73MiB nodes=49,616,912@12.67GiB pending=29805
|
||||
```
|
||||
|
||||
{% include note.html content="Snap syncing Goerli will take some time and until the sync is finished you can't use the node to transfer funds. You can also try doing a [light sync](interface/les) which will be much quicker but depends on light servers being available to serve your node the data it needs." %}
|
||||
When state healing is finished, the node is in sync and ready to use.
|
||||
|
||||
## Step 3: Get Testnet Ether
|
||||
Sending an empty Curl request to the http server provides a quick way to confirm that this too has been started without any issues. In a third terminal, the following command can be run:
|
||||
|
||||
In order to make some transactions, the user must fund their account with ether. On Ethereum mainnet, ether can only be obtained in three ways: 1) by receiving it as a reward for mining/validating; 2) receiving it in a transfer from another Ethereum user or contract; 3) receiving it from an exchange, having paid for it with fiat money. On Ethereum testnets, the ether has no real world value so it can be made freely available via faucets. Faucets allow users to request a transfer of testnet ether to their account.
|
||||
```shell
|
||||
curl http://localhost:8545
|
||||
```
|
||||
|
||||
The address generated by `geth account new` can be pasted into the Paradigm Multifaucet faucet [here](https://fauceth.komputing.org/?chain=1115511). This requires a Twitter login as proof of personhood. The faucets adds ether to the given address on multiple testnets simultaneously, including Goerli. In the next steps Geth will be used to check that the ether has been sent to the given address and send some of it to the second address created earlier.
|
||||
If there is no error message reported to the terminal, everything is OK. Geth must be running and synced in order for a user to interact with the Ethereum network. If the terminal running Geth is closed down then Geth must be restarted again in a new terminal. Geth can be started and stopped easily, but it must be running for any interaction with Ethereum to take place. To shut down Geth, simply press `CTRL+C` in the Geth terminal. To start it again, run the previous command `geth --datadir <other commands>`.
|
||||
|
||||
## Step 4: Interact with Geth
|
||||
## Step 4: Get Testnet Ether {#get-test-eth}
|
||||
|
||||
For interacting with the blockchain, Geth provides JSON-RPC APIs.
|
||||
[JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/) is a way to execute specific tasks by sending instructions to Geth in the form of [JSON](https://www.json.org/json-en.html) objects. RPC stands for "Remote Procedure Call" and it refers to the ability to send these JSON-encoded instructions from locations outside of those managed by Geth. It is possible to interact with Geth by sending these JSON encoded instructions directly to Geth using tools such as Curl. However, this is somewhat user-unfriendly and error-prone, especially for more complex instructions. For this reason, there are a set of libraries built on top of JSON-RPC that provide a more user-friendly interface for interacting with Geth. One of the most widely used is Web3.js.
|
||||
In order to make some transactions, the user must fund their account with ether. On Ethereum mainnet, ether can only be obtained in three ways: 1) by receiving it as a reward for mining/validating; 2) receiving it in a transfer from another Ethereum user or contract; 3) receiving it from an exchange, 3) having paid for it with fiat money. On Ethereum testnets, the ether has no real world value so it 4) can be made freely available via faucets. Faucets allow users to request a transfer of testnet ether to their account.
|
||||
|
||||
The address generated by Clef in Step 1 can be pasted into the Paradigm Multifaucet faucet [here](https://faucet.sepolia.dev/). The faucets adds Sepolia ETH (not real ETH) to the given address. In the next steps Geth will be used to check that the ether has been sent to the given address and send some of it to the second address created earlier.
|
||||
|
||||
## Step 5: Interact with Geth {#interact-with-geth}
|
||||
|
||||
For interacting with the blockchain, Geth provides JSON-RPC APIs. [JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/) is a way to execute specific tasks by sending instructions to Geth in the form of [JSON](https://www.json.org/json-en.html) objects. RPC stands for "Remote Procedure Call" and it refers to the ability to send these JSON-encoded instructions from locations outside of those managed by Geth. It is possible to interact with Geth by sending these JSON encoded instructions directly over Geth's exposed http port using tools like Curl. However, this is somewhat user-unfriendly and error-prone, especially for more complex instructions. For this reason, there are a set of libraries built on top of JSON-RPC that provide a more user-friendly interface for interacting with Geth. One of the most widely used is Web3.js.
|
||||
|
||||
Geth provides a Javascript console that exposes the Web3.js API. This means that with Geth running in one terminal, a Javascript environment can be opened in another allowing the user to interact with Geth using Web3.js. There are three transport protocols that can be used to connect the Javascript environment to Geth:
|
||||
|
||||
- IPC (Inter-Process Communication): Provides unrestricted access to all APIs, but only works when the console is run on the same host as the Geth node.
|
||||
- IPC (Inter-Process Communication): Provides unrestricted access to all APIs, but only works when the console is run on the same host as the geth node.
|
||||
- HTTP: By default provides access to the `eth`, `web3` and `net` method namespaces.
|
||||
|
||||
- Websocket: By default provides access to the `eth`, `web3` and `net` method namespaces.
|
||||
|
||||
This tutorial will use the IPC option. To do this, the path to Geth's `ipc` file must be known. By default, this is the `datadir`, in this case `geth-tutorial`. In a new terminal, the following command can be run to start the Javascript console and connect it to Geth using the `geth.ipc` file from the datadir:
|
||||
This tutorial will use the HTTP option. Note that the terminals running Geth and Clef should both still be active. In a new (third) terminal, the following command can be run to start the console and connect it to Geth using the exposed http port:
|
||||
|
||||
```shell
|
||||
geth attach geth-tutorial/geth.ipc
|
||||
geth attach http://127.0.0.1:8545
|
||||
```
|
||||
|
||||
The following welcome message will be displayed in the Javascript console:
|
||||
This command causes the terminal to hang because it is waiting for approval from Clef. Approving the request in the terminal running Clef will lead to the following welcome message being displayed in the Javascript console:
|
||||
|
||||
```terminal
|
||||
Welcome to the Geth JavaScript console!
|
||||
|
||||
instance: Geth/v1.10.15-stable/darwin-amd64/go1.17.5
|
||||
at block: 6354736 (Thu Feb 10 2022 14:01:46 GMT+0100 (WAT))
|
||||
datadir: /home/go-ethereum/geth-tutorial
|
||||
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0
|
||||
modules: eth:1.0 net:1.0 rpc:1.0 web3:1.0
|
||||
|
||||
To exit, press ctrl-d or type exit
|
||||
```
|
||||
|
||||
The console is now active and connected to Geth. It can now be used to interact with the Ethereum (Goerli) network.
|
||||
The console is now active and connected to Geth. It can now be used to interact with the Ethereum (Sepolia) network.
|
||||
|
||||
### List of accounts
|
||||
### List of accounts {#list-accounts}
|
||||
|
||||
Earlier in this tutorial, at least one account was created using `geth account new`. The following command will display the addresses of those two accounts and any others that might have been added to the keystore before or since.
|
||||
In this tutorial, the accounts are managed using Clef. This means that requesting information about the accounts requires explicit approval in Clef, which should still be running in its own terminal. Earlier in this tutorial, two accounts were created using Clef. The following command will display the addresses of those two accounts and any others that might have been added to the keystore before or since.
|
||||
|
||||
```javascript
|
||||
eth.accounts;
|
||||
```
|
||||
|
||||
The console will hang, because Clef is waiting for approval. The following message will be displayed in the Clef terminal:
|
||||
|
||||
```terminal
|
||||
-------- List Account request--------------
|
||||
A request has been made to list all accounts.
|
||||
You can select which accounts the caller can see
|
||||
[x] 0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC
|
||||
URL: keystore:///.../geth-tutorial/keystore/UTC--2022-02-07T17-19-56.517538000Z--ca57f3b40b42fcce3c37b8d18adbca5260ca72ec
|
||||
[x] 0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
URL: keystore:///.../geth-tutorial/keystore/UTC--2022-02-10T12-46-45.265592000Z--ce8dba5e4157c2b284d8853afeeea259344c1653
|
||||
-------------------------------------------
|
||||
Request context:
|
||||
NA - ipc - NA
|
||||
|
||||
Additional HTTP header data, provided by the external caller:
|
||||
User-Agent: ""
|
||||
Origin: ""
|
||||
Approve? [y/N]:
|
||||
|
||||
```
|
||||
|
||||
Entering `y` approves the request from the console. In the terminal running the Javascript console, the account addresses are now displayed:
|
||||
|
||||
```terminal
|
||||
["0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec", "0xce8dba5e4157c2b284d8853afeeea259344c1653"]
|
||||
```
|
||||
|
||||
### Checking account balance.
|
||||
It is also possible for this request to time out if the Clef approval took too long - in this case simply repeat the request and approval. Accoutns can also be listed directly from Clef by opening a new terminal and running `clef list-accounts --keystore <path-to-keystore>`.
|
||||
|
||||
Having confirmed that the two addresses created earlier are indeed in the keystore and accessible through the Javascript console, it is possible to retrieve information about how much ether they own. The Goerli faucet should have sent 1 ETH to the address provided, meaning that the balance of one of the accounts should be 1 ether and the other should be 0. The following command displays the account balance in the console:
|
||||
### Checking account balance. {#checking-balances}
|
||||
|
||||
Having confirmed that the two addresses created earlier are indeed in the keystore and accessible through the Javascript console, it is possible to retrieve information about how much ether they own. The Sepolia faucet should have sent 0.05 ETH to the address provided, meaning that the balance of one of the accounts should be at least 0.05 ether and the other should be 0. There are other faucets available that may dispense more ETH per request, and multipel requests can be made to accumulate more ETH. The following command displays the account balance in the console:
|
||||
|
||||
```javascript
|
||||
web3.fromWei(eth.getBalance('0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC'), 'ether');
|
||||
```
|
||||
|
||||
There are actually two instructions sent in the above command. The inner one is the `getBalance` function from the `eth` namespace. This takes the account address as its only argument. By default, this returns the account balance in units of Wei. There are 10<sup>18</sup> Wei to one ether. To present the result in units of ether, `getBalance` is wrapped in the `fromWei` function from the `web3` namespace. Running this command should provide the following result (for the account that
|
||||
received faucet funds):
|
||||
There are actually two instructions sent in the above command. The inner one is the `getBalance` function from the `eth` namespace. This takes the account address as its only argument. By default, this returns the account balance in units of Wei. There are 10<sup>18</sup> Wei to one ether. To present the result in units of ether, `getBalance` is wrapped in the `fromWei` function from the `web3` namespace. Running this command should provide the following result, assuming the account balance is 1 ETH:
|
||||
|
||||
```terminal
|
||||
1
|
||||
```
|
||||
|
||||
Repeating the command for the other new account that was not funded from the faucet should yield:
|
||||
Repeating the command for the other (empty) account should yield:
|
||||
|
||||
```terminal
|
||||
0
|
||||
```
|
||||
|
||||
### Send ether to another account
|
||||
### Send ether to another account {#sending-ether}
|
||||
|
||||
The command `eth.sendTransaction` can be used to send some ether from one address to another. This command takes three arguments: `from`, `to` and `value`. These define the sender and recipient addresses (as strings) and the amount of Wei to transfer. It is far less error prone to enter the transaction value in units of ether rather than Wei, so the value field can take the return value from the `toWei` function. The following command, run in the Javascript console, sends 0.1 ether from one of the accounts in the keystore to the other. Note that the addresses here are examples - the user must replace the address in the `from` field with the address currently owning 1 ether, and the address in the `to` field with the address currently holding 0 ether.
|
||||
The command `eth.sendTransaction` can be used to send some ether from one address to another. This command takes three arguments: `from`, `to` and `value`. These define the sender and recipient addresses (as strings) and the amount of Wei to transfer. It is far less error prone to enter the transaction value in units of ether rather than Wei, so the value field can take the return value from the `toWei` function. The following command, run in the Javascript console, sends 0.1 ether from one of the accounts in the Clef keystore to the other. Note that the addresses here are examples - the user must replace the address in the `from` field with the address currently owning 1 ether, and the address in the `to` field with the address currently holding 0 ether.
|
||||
|
||||
```javascript
|
||||
eth.sendTransaction({
|
||||
|
@ -201,7 +273,55 @@ eth.sendTransaction({
|
|||
});
|
||||
```
|
||||
|
||||
This command will return an error message indicating that `authentication is needed: password or unlock`. This is a security feature that prevents unauthorized access to sensitive account operations. There are two ways to unlock the account. The first is to start Geth with the account permanently unlocked (by passing `--unlock <address>` at startup). This is not recommended because the account remains unlocked all the time Geth is running, creating a security weakness. Instead, it is better to temporarily unlock the account for the specific transaction using Clef. This requires Geth to be started with Clef as an external signer, and for Clef to know the location of the keystore (please see the [account management](/docs/fundamentals/account-management) or [Clef](/docs/tools/clef/Introduction) pages for setup details).
|
||||
Note that submitting this transaction requires approval in Clef. In the Clef terminal, Clef will prompt for approval and request the account password. If the password is correctly entered, Geth proceeds with the transaction. The transaction request summary is presented by Clef in the Clef terminal. This is an opportunity for the sender to review the details and ensure they are correct.
|
||||
|
||||
```terminal
|
||||
--------- Transaction request-------------
|
||||
to: 0xCe8dBA5e4157c2B284d8853afEEea259344C1653
|
||||
from: 0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC [chksum ok]
|
||||
value: 10000000000000000 wei
|
||||
gas: 0x5208 (21000)
|
||||
maxFeePerGas: 2425000057 wei
|
||||
maxPriorityFeePerGas: 2424999967 wei
|
||||
nonce: 0x3 (3)
|
||||
chainid: 0x5
|
||||
Accesslist
|
||||
|
||||
Request context:
|
||||
NA - ipc - NA
|
||||
|
||||
Additional HTTP header data, provided by the external caller:
|
||||
User-Agent: ""
|
||||
Origin: ""
|
||||
-------------------------------------------
|
||||
Approve? [y/N]:
|
||||
|
||||
Please enter the password for account 0xca57F3b40B42FCce3c37B8D18aDBca5260ca72EC
|
||||
```
|
||||
|
||||
After approving the transaction, the following confirmation screen in displayed in the Clef terminal:
|
||||
|
||||
```terminal
|
||||
-----------------------
|
||||
Transaction signed:
|
||||
{
|
||||
"type": "0x2",
|
||||
"nonce": "0x3",
|
||||
"gasPrice": null,
|
||||
"maxPriorityFeePerGas": "0x908a901f",
|
||||
"maxFeePerGas": "0x908a9079",
|
||||
"gas": "0x5208",
|
||||
"value": "0x2386f26fc10000",
|
||||
"input": "0x",
|
||||
"v": "0x0",
|
||||
"r": "0x66e5d23ad156e04363e68b986d3a09e879f7fe6c84993cef800bc3b7ba8af072",
|
||||
"s": "0x647ff82be943ea4738600c831c4a19879f212eb77e32896c05055174045da1bc",
|
||||
"to": "0xce8dba5e4157c2b284d8853afeeea259344c1653",
|
||||
"chainId": "0xaa36a7",
|
||||
"accessList": [],
|
||||
"hash": "0x99d489d0bd984915fd370b307c2d39320860950666aac3f261921113ae4f95bb"
|
||||
}
|
||||
```
|
||||
|
||||
In the Javascript console, the transaction hash is displayed. This will be used in the next section to retrieve the transaction details.
|
||||
|
||||
|
@ -209,11 +329,11 @@ In the Javascript console, the transaction hash is displayed. This will be used
|
|||
"0x99d489d0bd984915fd370b307c2d39320860950666aac3f261921113ae4f95bb"
|
||||
```
|
||||
|
||||
It is also advised to check the account balances using Geth by repeating the instructions from earlier. At this point in the tutorial, the two accounts in the keystore should have balances just below 0.9 ether (because 0.1 ether has been transferred out and some small amount paid in transaction gas) and 0.1 ether.
|
||||
It is also advised to check the account balances using Geth by repeating the instructions from earlier. At this point in the tutorial, the balances of the two accounts in the Clef keystore should have changed by ~0.1 ETH (the sender's balance will have decremented by a little over 0.1 ETH because some small was amount paid in transaction gas).
|
||||
|
||||
### Checking the transaction hash
|
||||
### Checking the transaction hash {#checking-transaction-hash}
|
||||
|
||||
The transaction hash is a unique identifier for this specific transaction that can be used later to retrieve the transaction details. For example, the transaction details can be viewed by pasting this hash into the [Goerli block explorer](https://goerli.etherscan.io/). The same information can also be retrieved directly from the Geth node. The hash returned in the previous step can be provided as an argument to `eth.getTransaction` to return the transaction information:
|
||||
The transaction hash is a unique identifier for this specific transaction that can be used later to retrieve the transaction details. For example, the transaction details can be viewed by pasting this hash into the [Sepolia block explorer](https://sepolia.etherscan.io/). The same information can also be retrieved directly from the Geth node. The hash returned in the previous step can be provided as an argument to `eth.getTransaction` to return the transaction information:
|
||||
|
||||
```javascript
|
||||
eth.getTransaction('0x99d489d0bd984915fd370b307c2d39320860950666aac3f261921113ae4f95bb');
|
||||
|
@ -226,7 +346,7 @@ This returns the following response (although the actual values for each field w
|
|||
accessList: [],
|
||||
blockHash: "0x1c5d3f8dd997b302935391b57dc3e4fffd1fa2088ef2836d51f844f993eb39c4",
|
||||
blockNumber: 6355150,
|
||||
chainId: "0x5",
|
||||
chainId: "0xaa36a7",
|
||||
from: "0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec",
|
||||
gas: 21000,
|
||||
gasPrice: 2425000023,
|
||||
|
@ -245,11 +365,11 @@ This returns the following response (although the actual values for each field w
|
|||
}
|
||||
```
|
||||
|
||||
## Using Curl
|
||||
## Using Curl {#using-curl}
|
||||
|
||||
Up to this point this tutorial has interacted with Geth using the convenience library Web3.js. This library enables the user to send instructions to Geth using a more user-friendly interface compared to sending raw JSON objects. However, it is also possible for the user to send these JSON objects directly to Geth's exposed HTTP port. Curl is a command line tool that sends HTTP requests. This part of the tutorial demonstrates how to check account balances and send a transaction using Curl. This requires Geth to expose an HTTP port to listen for requests. This can be configured at startup by passing the `--http` flag. If no other commands are passed with it, `--http` will expose the default `localhost:8545` port.
|
||||
Up to this point this tutorial has interacted with Geth using the convenience library Web3.js. This library enables the user to send instructions to Geth using a more user-friendly interface compared to sending raw JSON objects. However, it is also possible for the user to send these JSON objects directly to Geth's exposed HTTP port. Curl is a command line tool that sends HTTP requests. This part of the tutorial demonstrates how to check account balances and send a transaction using Curl.
|
||||
|
||||
### Checking account balance
|
||||
### Checking account balance {#checking-balance}
|
||||
|
||||
The command below returns the balance of the given account. This is a HTTP POST request to the local port 8545. The `-H` flag is for header information. It is used here to define the format of the incoming payload, which is JSON. The `--data` flag defines the content of the payload, which is a JSON object. That JSON object contains four fields: `jsonrpc` defines the spec version for the JSON-RPC API, `method` is the specific function being invoked, `params` are the function arguments, and `id` is used for ordering transactions. The two arguments passed to `eth_getBalance` are the account address whose balance to check and the block to query (here `latest` is used to check the balance in the most recently mined block).
|
||||
|
||||
|
@ -277,7 +397,7 @@ This returns the balance in ether:
|
|||
0.8999684999998321
|
||||
```
|
||||
|
||||
### Checking the account list
|
||||
### Checking the account list {#checking-account-list}
|
||||
|
||||
The curl command below returns the list of all accounts.
|
||||
|
||||
|
@ -287,18 +407,28 @@ curl -X POST http://127.0.0.1:8545 \
|
|||
--data '{"jsonrpc":"2.0", "method":"eth_accounts","params":[], "id":1}'
|
||||
```
|
||||
|
||||
The following information is returned to the terminal:
|
||||
This requires approval in Clef. Once approved, the following information is returned to the terminal:
|
||||
|
||||
```terminal
|
||||
{"jsonrpc":"2.0","id":1,"result":["0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec"]}
|
||||
```
|
||||
|
||||
### Sending Transactions
|
||||
### Sending Transactions {#sending-transactions}
|
||||
|
||||
It is possible to send transactions using raw curl requests too, but this requires unlocking the sender account. It is recommended to do this using Clef to manage access to accounts or to use `ipc` instead. The combination of HTTP and unlocked accounts pose a security risk.
|
||||
Sending a transaction between accounts can also be achieved using Curl. Notice that the value of the transaction is a hexadecimal string in units of Wei. To transfer 0.1 ether, it is first necessary to convert this to Wei by multiplying by 10<sup>18</sup> then converting to hex. 0.1 ether is `"0x16345785d8a0000"` in hex. As before, update the `to` and `from` fields with the addresses in the Clef keystore.
|
||||
|
||||
## Summary
|
||||
```shell
|
||||
curl -X POST http://127.0.0.1:8545 \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0", "method":"eth_sendTransaction", "params":[{"from": "0xca57f3b40b42fcce3c37b8d18adbca5260ca72ec","to": "0xce8dba5e4157c2b284d8853afeeea259344c1653","value": "0x16345785d8a0000"}], "id":1}'
|
||||
```
|
||||
|
||||
This tutorial has demonstrated how to generate accounts using Geth's built-in account management tool, fund them with testnet ether and use those accounts to interact with Ethereum (Goerli) through a Geth node. Checking account balances, sending transactions and retrieving transaction details were explained using
|
||||
the web3.js library via the Geth console and using the JSON-RPC directly using Curl. Note that this is an entry-level tutorial designed to help users get familiar with basic Geth processes, we strongly recommend following this with the [Geth with Clef](/docs/getting-started/geth_with_clef) tutorial which will help to
|
||||
adopt more secure account management practices than those outlined here.
|
||||
This requires approval in Clef. Once the password for the sender account has been provided, Clef will return a summary of the transaction details and the terminal that made the Curl request will display a response containing the transaction hash.
|
||||
|
||||
```terminal
|
||||
{"jsonrpc":"2.0","id":5,"result":"0xac8b347d70a82805edb85fc136fc2c4e77d31677c2f9e4e7950e0342f0dc7e7c"}
|
||||
```
|
||||
|
||||
## Summary {#summary}
|
||||
|
||||
This tutorial has demonstrated how to generate accounts using Clef, fund them with testnet ether and use those accounts to interact with Ethereum (Sepolia) through a Geth node. Checking account balances, sending transactions and retrieving transaction details were explained using the web3.js library via the Geth console and using the JSON-RPC directly using Curl. For more detailed information about Clef, please see [the Clef docs](/docs/tools/Clef/Tutorial).
|
||||
|
|
|
@ -5,9 +5,9 @@ description: Guide to installing Geth
|
|||
|
||||
There are several ways to install Geth, including via a package manager, downloading a pre-built bundle, running as a docker container or building from downloaded source code. On this page the various installation options are explained for several major operating systems. Users prioritizing ease of installation should choose to use a package manager or prebuilt bundle. Users prioritizing customization should build from source. It is important to run the latest version of Geth because each release includes bugfixes and improvement over the previous versions. The stable releases are recommended for most users because they have been fully tested. A list of stable releases can be found [here](https://github.com/ethereum/go-ethereum/releases). Instructions for updating existing Geth installations are also provided in each section.
|
||||
|
||||
## Package managers
|
||||
## Package managers {#package-managers}
|
||||
|
||||
### MacOS via Homebrew
|
||||
### MacOS via Homebrew {#macos-via-homebrew}
|
||||
|
||||
The easiest way to install go-ethereum is to use the Geth Homebrew tap. The first step is to check that Homebrew is installed. The following command should return a version number.
|
||||
|
||||
|
@ -40,7 +40,7 @@ brew reinstall ethereum
|
|||
|
||||
When the node is started again, Geth will automatically use all the data from the previous version and sync the blocks that were missed while the node was offline.
|
||||
|
||||
### Ubuntu via PPAs
|
||||
### Ubuntu via PPAs {#ubuntu-via-ppas}
|
||||
|
||||
The easiest way to install Geth on Ubuntu-based distributions is with the built-in launchpad PPAs (Personal Package Archives). A single PPA repository is provided, containing stable and development releases for Ubuntu versions `xenial`, `trusty`, `impish`, `focal`, `bionic`.
|
||||
|
||||
|
@ -76,13 +76,13 @@ sudo apt-get upgrade geth
|
|||
|
||||
When the node is started again, Geth will automatically use all the data from the previous version and sync the blocks that were missed while the node was offline.
|
||||
|
||||
### Windows
|
||||
### Windows {#windows}
|
||||
|
||||
The easiest way to install Geth is to download a pre-compiled binary from the [downloads](/downloads) page. The page provides an installer as well as a zip file containing the Geth source code. The install wizard offers the user the option to install Geth, or Geth and the developer tools. The installer adds `geth` to the system's `PATH` automatically. The zip file contains the command `.exe` files that can be run from the command prompt. The full list of command line options can be viewed [here](/docs/fundamentals/Command-Line-Options) or in the terminal by running `geth --help`.
|
||||
|
||||
Updating an existing Geth installation can be achieved by stopping the node, downloading and installing the latest version following the instructions above. When the node is started again, Geth will automatically use all the data from the previous version and sync the blocks that were missed while the node was offline.
|
||||
|
||||
### FreeBSD via pkg
|
||||
### FreeBSD via pkg {#freeBSD-via-pkg}
|
||||
|
||||
Geth can be installed on FreeBSD using the package manager `pkg`. The following command downloads and installs Geth:
|
||||
|
||||
|
@ -102,7 +102,7 @@ pkg upgrade
|
|||
|
||||
When the node is started again, Geth will automatically use all the data from the previous version and sync the blocks that were missed while the node was offline.
|
||||
|
||||
### FreeBSD via ports
|
||||
### FreeBSD via ports {#freeBSD-via-ports}
|
||||
|
||||
Installing Geth using ports, simply requires navigating to the `net-p2p/go-ethereum` ports directory and running `make install` as root:
|
||||
|
||||
|
@ -123,7 +123,7 @@ portsnap fetch
|
|||
|
||||
When the node is started again, Geth will automatically use all the data from the previous version and sync the blocks that were missed while the node was offline.
|
||||
|
||||
### Arch Linux via pacman
|
||||
### Arch Linux via pacman {#arch-linux-via-pacman}
|
||||
|
||||
The Geth package is available from the [community repo](https://www.archlinux.org/packages/community/x86_64/geth/). It can be installed by running:
|
||||
|
||||
|
@ -143,7 +143,7 @@ sudo pacman -Sy
|
|||
|
||||
When the node is started again, Geth will automatically use all the data from the previous version and sync the blocks that were missed while the node was offline.
|
||||
|
||||
## Standalone bundle
|
||||
## Standalone bundle {#standalone-bundle}
|
||||
|
||||
Stable releases and development builds are provided as standalone bundles. These are useful for users who: a) wish to install a specific version of Geth (e.g., for reproducible environments); b) wish to install on machines without internet access (e.g. air-gapped computers); or c) wish to avoid automatic updates and instead prefer to manually install software.
|
||||
|
||||
|
@ -157,7 +157,7 @@ Some archives contain only Geth, while other archives containing Geth and the va
|
|||
|
||||
The standalone bundles can be downloaded from the [Geth Downloads](/downloads) page. To update an existing installation, download and manually install the latest version.
|
||||
|
||||
## Docker container
|
||||
## Docker container {#docker-container}
|
||||
|
||||
A Docker image with recent snapshot builds from our `develop` branch is maintained on DockerHub to support users who prefer to run containerized processes. There four different Docker images available for running the latest stable or development versions of Geth.
|
||||
|
||||
|
@ -197,9 +197,9 @@ docker pull ethereum/client-go:latest
|
|||
docker run -it -p 30303:30303 ethereum/client-go
|
||||
```
|
||||
|
||||
## Build from source code
|
||||
## Build from source code {#build-from-source}
|
||||
|
||||
### Most Linux systems and macOS
|
||||
### Most Linux systems and macOS {#linux-and-macos}
|
||||
|
||||
Geth is written in [Go](https://golang.org/), so building from source code requires the most recent version of Go to be installed. Instructions for installing Go are available at the [Go installation page](https://golang.org/doc/install) and necessary bundles can be downloaded from the [Go download page](https://golang.org/dl/).
|
||||
|
||||
|
@ -236,7 +236,7 @@ Updating an existing Geth installation can be achieved using `go get`:
|
|||
go get -u github.com/ethereum/go-ethereum
|
||||
```
|
||||
|
||||
### Windows
|
||||
### Windows {#windows}
|
||||
|
||||
The Chocolatey package manager provides an easy way to install the required build tools. Chocolatey can be installed by following these [instructions](https://chocolatey.org). Then, to install the build tool the following commands can be run in an Administrator command prompt:
|
||||
|
||||
|
@ -256,7 +256,7 @@ C:\Users\xxx\src\github.com\ethereum\go-ethereum> go get -u -v golang.org/x/net/
|
|||
C:\Users\xxx\src\github.com\ethereum\go-ethereum> go install -v ./cmd/...
|
||||
```
|
||||
|
||||
### FreeBSD
|
||||
### FreeBSD {#freeBSD}
|
||||
|
||||
To build Geth from source code on FreeBSD, the Geth Github repository can be cloned into a local directory.
|
||||
|
||||
|
@ -290,7 +290,7 @@ To start the node, the followijng command can be run:
|
|||
build/bin/geth
|
||||
```
|
||||
|
||||
### Building without a Go workflow
|
||||
### Building without a Go workflow {#building-without-go}
|
||||
|
||||
Geth can also be built without using Go workspaces. In this case, the repository should be cloned to a local repository. Then, the command
|
||||
`make geth` configures everything for a temporary build and cleans up afterwards. This method of building only works on UNIX-like operating systems, and a Go installation is still required.
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
---
|
||||
title: Welcome to go-ethereum documentation
|
||||
title: Welcome to go-ethereum
|
||||
description: Documentation for the go-ethereum client
|
||||
---
|
||||
|
||||
## Welcome to go-ethereum
|
||||
|
||||
Go-ethereum (aka Geth) is an Ethereum client built in [Golang](https://go.dev). It is one of the original and most popular Ethereum clients.
|
||||
These documentation pages are intended to help users download, install and use Geth.
|
||||
|
||||
## Where to go from here
|
||||
## Where to go from here {#where-to-go}
|
||||
|
||||
First, make sure you have sufficient [hardware](/docs/getting-started/hardware-requirements), then [download](/downloads) and [install](/docs/getting-started/installing-geth) Geth. Make sure you are familiar with the [security considerations](/docs/fundamentals/security) and have your firewall set up.
|
||||
|
||||
If you are just starting out with Geth, head to the [Getting started](/docs/getting-started/) page. That page guides a new user through some basic functions of Geth such as creating and securing accounts and making a transaction using Geth's built-in account tools.
|
||||
|
||||
A more secure but slightly more advanced setup is to use an external signer instead of Geth's built-in account manager. We have a [getting started](/docs/getting-started/getting-started-with-clef) guide for that too.
|
||||
If you are just starting out with Geth, head to the [Getting started](/docs/getting-started/) page. That page guides new users through some basic functions of Geth such as creating and securing accounts and making a transaction.
|
||||
|
||||
Then, it is recommended to read the material in the [Fundamentals](/docs/fundamentals) section - these pages will help build a foundational understanding of how Geth works from a user perspective and under the hood.
|
||||
|
||||
More advanced topics are also available - explore them using the sidebar!
|
||||
|
||||
## Developers and contributors
|
||||
## Developers and contributors {#developers-and-contributors}
|
||||
|
||||
If you want to help develop Geth or build decentralized apps on top of it, head to our [Developers](/docs/developers) documentation.
|
||||
|
||||
## More resources
|
||||
## More resources {#more-resources}
|
||||
|
||||
We have a library of videos and articles on our [Resources](/docs/resources) page and answers to common questions on the [FAQs](/docs/faq) page.
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Instructions for working with contracts in the Javascript console.
|
|||
|
||||
The [Introduction to the Javascript console](/docs/interacting-with-geth/javascript-console) page outlined how a Javascript console can be attached to Geth to provide a more user-friendly interface to Ethereum than interacting directly with the JSON-RPC API. This page will describe how to deploy contracts and interact with contracts using the attached console. This page will assume the Javascript console is attached to a running Geth instance using IPC. Clef should be used to manage accounts.
|
||||
|
||||
## Deploying a contract
|
||||
## Deploying a contract {#deploying-a-contract}
|
||||
|
||||
First we need a contract to deploy. We can use the well-known `Storage.sol` contract written in Solidity. The following Solidity code can be copied and pasted into a text editor and saved as `go-ethereum/storage-contract/Storage.sol`.
|
||||
|
||||
|
@ -128,6 +128,6 @@ contract.set.sendTransaction(42, { from: eth.accounts[0], gas: 1000000 });
|
|||
contract.retrieve().call() >> 2;
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page demonstrated how to create, compile, deploy and interact with an Ethereum smart contract using Geth's Javascript console.
|
||||
|
|
|
@ -20,7 +20,7 @@ The purpose of Geth's Javascript console is to provide a built-in environment to
|
|||
|
||||
{% include note.html content="The web3.js version that comes bundled with Geth is not up to date with the official Web3.js documentation. There are several Web3.js libraries that are not available in the Geth Javascript Console. There are also administrative APIs included in the Geth console that are not documented in the Web3.js documentation. The full list of libraries available in the Geth console is available on the [JSON-RPC API page](/docs/rpc/server)." %}
|
||||
|
||||
## Starting the console
|
||||
## Starting the console {#starting-the-console}
|
||||
|
||||
There are two ways to start an interactive session using Geth console. The first is to provide the `console` command when Geth is started up. This starts the node and runs the console in the same terminal. It is therefore convenient to suppress the logs from the node to prevent them from obscuring the console. If the logs are not needed, they can be redirected to the `dev/null` path, effectively muting them. Alternatively, if the logs are required they can be redirected to a text file. The level of detail provided in the logs can be adjusted by providing a value between 1-6 to the `--verbosity` flag as in the example below:
|
||||
|
||||
|
@ -75,7 +75,7 @@ To exit, press ctrl-d or type exit
|
|||
>
|
||||
```
|
||||
|
||||
## Interactive use
|
||||
## Interactive use {#interactive-use}
|
||||
|
||||
Once the console has been started, it can be used to interact with Geth. The console supports Javascript and the full Geth [JSON-RPC API](/docs/rpc/server). For example:
|
||||
|
||||
|
@ -107,7 +107,7 @@ Once the interactive session is over, the console can be closed down by typing `
|
|||
|
||||
Remember that interactions that touch accounts need approval in Clef - either manually or by writing a custom ruleset.
|
||||
|
||||
## Non-interactive Use: Script Mode
|
||||
## Non-interactive Use: Script Mode {#non-interactive-use}
|
||||
|
||||
It is also possible to execute JavaScript code non-interactively by passing the `--exec` and a JSON-RPC-API endpoint
|
||||
to `geth attach` or `geth console`. The result is displayed directly in the terminal rather than in an interactive Javascript console.
|
||||
|
@ -133,10 +133,10 @@ geth attach http://geth.example.org:8545 --jspath "/tmp" --exec 'loadScript("che
|
|||
The `--jspath` flag is used to set a library directory for the Javascript scripts. Any parameters passed to `loadScript()`
|
||||
that do not explicitly define an absolute path will be interpreted relative to the `jspath` directory.
|
||||
|
||||
## Timers
|
||||
## Timers {#timers}
|
||||
|
||||
In addition to the full functionality of JS (as per ECMA5), the Ethereum Javascript Runtime Environment (JSRE) is augmented with various timers. It implements `setInterval`, `clearInterval`, `setTimeout`, `clearTimeout` which some users will be familiar with from browser windows. It also provides implementation for `admin.sleep(seconds)` and a block based timer, `admin.sleepBlocks(n)` which sleeps till the number of new blocks added is equal to or greater than `n`.
|
||||
|
||||
## Caveats
|
||||
## Caveats {#caveats}
|
||||
|
||||
Geth's console is built using the [GoJa JS Virtual Machine](https://github.com/dop251/goja) which is compatible with ECMAScript 5.1. This does not support promises or `async` functions. Web3js depends upon the `bignumber.js` library. This is auto-loaded into the console.
|
||||
|
|
|
@ -17,7 +17,7 @@ Now queries can be raised against `http://localhost:8545/graphql`. To change the
|
|||
geth --http --http.port 9545 --graphql
|
||||
```
|
||||
|
||||
## GraphiQL
|
||||
## GraphiQL {#graphiql}
|
||||
|
||||
An easy way to try out queries is the GraphiQL interface shipped with Geth. To open it visit `http://localhost:8545/graphql/ui`. To see how this works let's read the sender, recipient and value of all transactions in block number 6000000. In GraphiQL:
|
||||
|
||||
|
@ -40,7 +40,7 @@ query txInfo {
|
|||
|
||||
GraphiQL also provides a way to explore the schema Geth provides to help you formulate your queries, which you can see on the right sidebar. Under the title `Root Types` click on `Query` to see the high-level types and their fields.
|
||||
|
||||
## Query
|
||||
## Query {#query}
|
||||
|
||||
Reading out data from Geth is the biggest use-case for GraphQL. In addition to using the UI queries can also be sent programmatically. The official GraphQL[docs](https://graphql.org/code/) explain how to find bindings for many languages, or send http requests from the terminal using tools such as Curl.
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ description: Introduction to the JSON_RPC server
|
|||
Interacting with Geth requires sending requests to specific JSON-RPC API methods. Geth supports all standard [JSON-RPC API](https://github.com/ethereum/execution-apis) endpoints.
|
||||
The RPC requests must be sent to the node and the response returned to the client using some transport protocol. This page outlines the available transport protocols in Geth, providing the information users require to choose a transport protocol for a specific user scenario.
|
||||
|
||||
## Introduction
|
||||
## Introduction {#introduction}
|
||||
|
||||
JSON-RPC is provided on multiple transports. Geth supports JSON-RPC over HTTP, WebSocket and Unix Domain Sockets. Transports must be enabled through
|
||||
command-line flags.
|
||||
|
@ -16,11 +16,11 @@ the namespace, an underscore, and the actual method name within the namespace. F
|
|||
|
||||
Access to RPC methods can be enabled on a per-namespace basis. Find documentation for individual namespaces in the sidebar.
|
||||
|
||||
## Transports
|
||||
## Transports {#transports}
|
||||
|
||||
There are three transport protocols available in Geth: IPC, HTTP and Websockets.
|
||||
|
||||
### HTTP Server
|
||||
### HTTP Server {#http-server}
|
||||
|
||||
[HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP) is a unidirectional transport protocol that connects a client and server. The client sends a request to the server, and the server returns a response back to the client. An HTTP connection is closed after the response for a given request is sent.
|
||||
|
||||
|
@ -56,7 +56,7 @@ The `--http.corsdomain` command also acceptsd wildcards that enable access to th
|
|||
--http.corsdomain '*'
|
||||
```
|
||||
|
||||
### WebSocket Server
|
||||
### WebSocket Server {#websockets-server}
|
||||
|
||||
Websocket is a bidirectional transport protocol. A Websocket connection is maintained by client and server until it is explicitly terminated by one. Most modern browsers support Websocket which means it has good tooling.
|
||||
|
||||
|
@ -80,7 +80,7 @@ As with `--http.corsdomain`, using the wildcard `--ws.origins '*'` allows access
|
|||
|
||||
{% include note.html content=" By default, **account unlocking is forbidden when HTTP or Websocket access is enabled** (i.e. by passing `--http` or `ws` flag). This is because an attacker that manages to access the node via the externally-exposed HTTP/WS port can then control the unlocked account. It is possible to force account unlock by including the `--allow-insecure-unlock` flag but this is unsafe and **not recommended** except for expert users that completely understand how it can be used safely. This is not a hypothetical risk: **there are bots that continually scan for http-enabled Ethereum nodes to attack**" %}
|
||||
|
||||
### IPC Server
|
||||
### IPC Server {#ipc-server}
|
||||
|
||||
IPC is normally available for use in local environments where the node and the console exist on the same machine. Geth creates a pipe in the computers local file system (at `ipcpath`) that configures a connection between node and console. The `geth.ipc` file can also be used by other processes on the same machine to interact with Geth.
|
||||
|
||||
|
@ -101,7 +101,7 @@ On Windows, IPC is provided via named pipes. The default location of the geth pi
|
|||
The location of the socket can be customized using the `--ipcpath` flag. IPC can be disabled
|
||||
using the `--ipcdisable` flag.
|
||||
|
||||
## Choosing a transport protocol
|
||||
## Choosing a transport protocol {#choosing-transport-protocol}
|
||||
|
||||
The following table summarizes the relative strengths and weaknesses of each transport protocol so that users can make informed decisions about which to use.
|
||||
|
||||
|
@ -114,12 +114,12 @@ The following table summarizes the relative strengths and weaknesses of each tra
|
|||
As a general rule IPC is most secure because it is limited to interactions on the local machine and cannot be exposed to external traffic. It can also be used
|
||||
to subscribe to events. HTTP is a familiar and idempotent transport that closes connections between requests and can therefore have lower overall overheads if the number of requests is fairly low. Websockets provides a continuous open channel that can enable event subscriptions and streaming and handle large volumes of requests with smaller per-message overheads.
|
||||
|
||||
## Engine-API
|
||||
## Engine-API {#engine-api}
|
||||
|
||||
The Engine-API is a set of RPC methods that enable communication between Geth and the [consensus client](/docs/getting_started/consensus-clients). These are not designed to be exposed to the user - instead they are called automatically by the clients when they need to exchange information. The Engine API is enabled by default - the user is not required to pass any instruction to Geth to enable these methods.
|
||||
|
||||
Read more in the [Engine API spec](https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md).
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
RPC requests to a Geth node can be made using three different transport protocols. The protocols are enabled at startup using their respective flags. The right choice of transport protocol depends on the specific use case.
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Documentation for the JSON-RPC API "admin" namespace
|
|||
|
||||
The `admin` API gives access to several non-standard RPC methods, which allows fine grained control over a Geth instance, including but not limited to network peer and RPC endpoint management.
|
||||
|
||||
## admin_addPeer
|
||||
## admin_addPeer {#admin-addpeer}
|
||||
|
||||
The `addPeer` administrative method requests adding a new remote node to the list of tracked static nodes. The node will try to maintain connectivity to these nodes at all times, reconnecting every once in a while if the remote connection goes down.
|
||||
|
||||
|
@ -24,7 +24,7 @@ The method accepts a single argument, the [`enode`](https://ethereum.org/en/deve
|
|||
true
|
||||
```
|
||||
|
||||
## admin_addTrustedPeer
|
||||
## admin_addTrustedPeer {#admin-addtrustedpeer}
|
||||
|
||||
Adds the given node to a reserved trusted list which allows the node to always connect, even if the slots are full. It returns a `BOOL` to indicate whether the peer was successfully added to the list.
|
||||
|
||||
|
@ -33,7 +33,7 @@ Adds the given node to a reserved trusted list which allows the node to always c
|
|||
| Console | `admin.addTrustedPeer(url)` |
|
||||
| RPC | `{"method": "admin_addTrustedPeer", "params": [url]}` |
|
||||
|
||||
## admin_datadir
|
||||
## admin_datadir {#admin-datadir}
|
||||
|
||||
The `datadir` administrative property can be queried for the absolute path the running Geth node currently uses to store all its databases.
|
||||
|
||||
|
@ -50,7 +50,7 @@ The `datadir` administrative property can be queried for the absolute path the r
|
|||
"/home/john/.ethereum"
|
||||
```
|
||||
|
||||
## admin_exportChain
|
||||
## admin_exportChain {#admin-exportchain}
|
||||
|
||||
Exports the current blockchain into a local file. It optionally takes a first and last block number, in which case it exports only that range of blocks. It returns a boolean indicating whether the operation succeeded.
|
||||
|
||||
|
@ -59,7 +59,7 @@ Exports the current blockchain into a local file. It optionally takes a first an
|
|||
| Console | `admin.exportChain(file, first, last)` |
|
||||
| RPC | `{"method": "admin_exportChain", "params": [string, uint64, uint64]}` |
|
||||
|
||||
## admin_importChain
|
||||
## admin_importChain {#admin-importchain}
|
||||
|
||||
Imports an exported list of blocks from a local file. Importing involves processing the blocks and inserting them into the canonical chain. The state from the parent block of this range is required. It returns a boolean indicating whether the operation succeeded.
|
||||
|
||||
|
@ -68,7 +68,7 @@ Imports an exported list of blocks from a local file. Importing involves process
|
|||
| Console | `admin.importChain(file)` |
|
||||
| RPC | `{"method": "admin_importChain", "params": [string]}` |
|
||||
|
||||
## admin_nodeInfo
|
||||
## admin_nodeInfo {#admin-nodeinfo}
|
||||
|
||||
The `nodeInfo` administrative property can be queried for all the information known about the running Geth node at the networking granularity. These include general information about the node itself as a participant of the [ÐΞVp2p](https://github.com/ethereum/devp2p/blob/master/caps/eth.md) P2P overlay protocol, as well as specialized information added by each of the running application protocols (e.g. `eth`, `les`, `shh`, `bzz`).
|
||||
|
||||
|
@ -103,7 +103,7 @@ The `nodeInfo` administrative property can be queried for all the information kn
|
|||
}
|
||||
```
|
||||
|
||||
## admin_peerEvents
|
||||
## admin_peerEvents {#admin-peerevents}
|
||||
|
||||
PeerEvents creates an [RPC subscription](/docs/rpc/pubsub) which receives peer events from the node's p2p server. The type of events emitted by the server are as follows:
|
||||
|
||||
|
@ -112,7 +112,7 @@ PeerEvents creates an [RPC subscription](/docs/rpc/pubsub) which receives peer e
|
|||
- `msgsend`: emitted when a message is successfully sent to a peer
|
||||
- `msgrecv`: emitted when a message is received from a peer
|
||||
|
||||
## admin_peers
|
||||
## admin_peers {#admin-peers}
|
||||
|
||||
The `peers` administrative property can be queried for all the information known about the connected remote nodes at the networking granularity. These include general information about the nodes themselves as participants of the [ÐΞVp2p](https://github.com/ethereum/devp2p/blob/master/caps/eth.md) P2P overlay protocol, as well as specialized information added by each of the running application protocols (e.g. `eth`, `les`, `shh`, `bzz`).
|
||||
|
||||
|
@ -159,7 +159,7 @@ The `peers` administrative property can be queried for all the information known
|
|||
}]
|
||||
```
|
||||
|
||||
## admin_removePeer
|
||||
## admin_removePeer {#admin-removepeer}
|
||||
|
||||
Disconnects from a remote node if the connection exists. It returns a boolean indicating validations succeeded. Note a `true` value doesn't necessarily mean that there was a connection which was disconnected.
|
||||
|
||||
|
@ -168,7 +168,7 @@ Disconnects from a remote node if the connection exists. It returns a boolean in
|
|||
| Console | `admin.removePeer(url)` |
|
||||
| RPC | `{"method": "admin_removePeer", "params": [string]}` |
|
||||
|
||||
## admin_removeTrustedPeer
|
||||
## admin_removeTrustedPeer {#admin-removetrustedpeer}
|
||||
|
||||
Removes a remote node from the trusted peer set, but it does not disconnect it automatically. It returns a boolean indicating validations succeeded.
|
||||
|
||||
|
@ -177,7 +177,7 @@ Removes a remote node from the trusted peer set, but it does not disconnect it a
|
|||
| Console | `admin.removeTrustedPeer(url)` |
|
||||
| RPC | `{"method": "admin_removeTrustedPeer", "params": [string]}` |
|
||||
|
||||
## admin_startHTTP
|
||||
## admin_startHTTP {#admin-starthttp}
|
||||
|
||||
The `startHTTP` administrative method starts an HTTP based JSON-RPC [API](/docs/rpc/server) webserver to handle client requests. All the parameters are optional:
|
||||
|
||||
|
@ -201,7 +201,7 @@ The method returns a boolean flag specifying whether the HTTP RPC listener was o
|
|||
true
|
||||
```
|
||||
|
||||
## admin_startWS
|
||||
## admin_startWS {#admin-startws}
|
||||
|
||||
The `startWS` administrative method starts an WebSocket based [JSON RPC](https://www.jsonrpc.org/specification) API webserver to handle client requests. All the parameters are optional:
|
||||
|
||||
|
@ -225,7 +225,7 @@ The method returns a boolean flag specifying whether the WebSocket RPC listener
|
|||
true
|
||||
```
|
||||
|
||||
## admin_stopHTTP
|
||||
## admin_stopHTTP {#admin-stophttp}
|
||||
|
||||
The `stopHTTP` administrative method closes the currently open HTTP RPC endpoint. As the node can only have a single HTTP endpoint running, this method takes no parameters, returning a boolean whether the endpoint was closed or not.
|
||||
|
||||
|
@ -242,7 +242,7 @@ The `stopHTTP` administrative method closes the currently open HTTP RPC endpoint
|
|||
true
|
||||
```
|
||||
|
||||
## admin_stopWS
|
||||
## admin_stopWS {#admin-stopws}
|
||||
|
||||
The `stopWS` administrative method closes the currently open WebSocket RPC endpoint. As the node can only have a single WebSocket endpoint running, this method takes no parameters, returning a boolean whether the endpoint was closed or not.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Documentation for the JSON-RPC API "clique" namespace
|
|||
|
||||
The `clique` API provides access to the state of the clique consensus engine. This API cna be used to manage signer votes and to check the health of a private network.
|
||||
|
||||
## clique_getSnapshot
|
||||
## clique_getSnapshot {#clique-getsnapshot}
|
||||
|
||||
Retrieves a snapshot of all clique state at a given block.
|
||||
|
||||
|
@ -41,7 +41,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
## clique_getSnapshotAtHash
|
||||
## clique_getSnapshotAtHash {#clique-getsnapshotathash}
|
||||
|
||||
Retrieves the state snapshot at a given block.
|
||||
|
||||
|
@ -50,7 +50,7 @@ Retrieves the state snapshot at a given block.
|
|||
| Console | `clique.getSnapshotAtHash(blockHash)` |
|
||||
| RPC | `{"method": "clique_getSnapshotAtHash", "params": [blockHash]}` |
|
||||
|
||||
## clique_getSigner
|
||||
## clique_getSigner {#clique-getsigner}
|
||||
|
||||
Returns the signer for a specific clique block. Can be called with either a blocknumber, blockhash or an rlp encoded blob. The RLP encoded blob can either be a block or a header.
|
||||
|
||||
|
@ -59,7 +59,7 @@ Returns the signer for a specific clique block. Can be called with either a bloc
|
|||
| Console | `clique.getSigner(blockNrOrHashOrRlp)` |
|
||||
| RPC | `{"method": "clique_getSigner", "params": [string]}` |
|
||||
|
||||
## clique_getSigners
|
||||
## clique_getSigners {#clique-getsigners}
|
||||
|
||||
Retrieves the list of authorized signers at the specified block number.
|
||||
|
||||
|
@ -68,7 +68,7 @@ Retrieves the list of authorized signers at the specified block number.
|
|||
| Console | `clique.getSigners(blockNumber)` |
|
||||
| RPC | `{"method": "clique_getSigners", "params": [blockNumber]}` |
|
||||
|
||||
## clique_getSignersAtHash
|
||||
## clique_getSignersAtHash {#clique-getsignersathash}
|
||||
|
||||
Retrieves the list of authorized signers at the specified block hash.
|
||||
|
||||
|
@ -77,7 +77,7 @@ Retrieves the list of authorized signers at the specified block hash.
|
|||
| Console | `clique.getSignersAtHash(blockHash)` |
|
||||
| RPC | `{"method": "clique_getSignersAtHash", "params": [string]}` |
|
||||
|
||||
## clique_proposals
|
||||
## clique_proposals {#clique-proposals}
|
||||
|
||||
Returns the current proposals the node is voting on.
|
||||
|
||||
|
@ -86,7 +86,7 @@ Returns the current proposals the node is voting on.
|
|||
| Console | `clique.proposals()` |
|
||||
| RPC | `{"method": "clique_proposals", "params": []}` |
|
||||
|
||||
## clique_propose
|
||||
## clique_propose {#clique-propose}
|
||||
|
||||
Adds a new authorization proposal that the signer will attempt to push through. If the `auth` parameter is true, the local signer votes for the given address to be included in the set of authorized signers. With `auth` set to `false`, the vote is against the address.
|
||||
|
||||
|
@ -95,7 +95,7 @@ Adds a new authorization proposal that the signer will attempt to push through.
|
|||
| Console | `clique.propose(address, auth)` |
|
||||
| RPC | `{"method": "clique_propose", "params": [address, auth]}` |
|
||||
|
||||
## clique_discard
|
||||
## clique_discard {#clique-discard}
|
||||
|
||||
This method drops a currently running proposal. The signer will not cast further votes (either for or against) the address.
|
||||
|
||||
|
@ -104,7 +104,7 @@ This method drops a currently running proposal. The signer will not cast further
|
|||
| Console | `clique.discard(address)` |
|
||||
| RPC | `{"method": "clique_discard", "params": [address]}` |
|
||||
|
||||
## clique_status
|
||||
## clique_status {#clique-status}
|
||||
|
||||
This is a debugging method which returns statistics about signer activity for the last 64 blocks. The returned object contains the following fields:
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
title: debug Namespace
|
||||
description: Documentation for the JSON-RPC API "clique" namespace
|
||||
description: methods in the debug namespace
|
||||
---
|
||||
|
||||
The `debug` API gives access to several non-standard RPC methods, which allow inspection, debugging and setting certain debugging flags during runtime.
|
||||
The `debug` API gives you access to several non-standard RPC methods, which will allow you to inspect, debug and set certain debugging flags during runtime.
|
||||
|
||||
## debug_accountRange
|
||||
### debug_accountRange
|
||||
|
||||
Enumerates all accounts at a given block with paging capability. `maxResults` are returned in the page and the items have keys that come after the `start` key (hashed address).
|
||||
|
||||
|
@ -16,7 +16,7 @@ If `incompletes` is false, then accounts for which the key preimage (i.e: the `a
|
|||
| Console | `debug.accountRange(blockNrOrHash, start, maxResults, nocode, nostorage, incompletes)` |
|
||||
| RPC | `{"method": "debug_getHeaderRlp", "params": [blockNrOrHash, start, maxResults, nocode, nostorage, incompletes]}` |
|
||||
|
||||
## debug_backtraceAt
|
||||
### debug_backtraceAt
|
||||
|
||||
Sets the logging backtrace location. When a backtrace location is set and a log message is emitted at that location, the stack of the goroutine executing the log statement will be printed to stderr.
|
||||
|
||||
|
@ -33,7 +33,7 @@ Example:
|
|||
> debug.backtraceAt("server.go:443")
|
||||
```
|
||||
|
||||
## debug_blockProfile
|
||||
### debug_blockProfile
|
||||
|
||||
Turns on block profiling for the given duration and writes profile data to disk. It uses a profile rate of 1 for most accurate information. If a different rate is desired, set the rate and write the profile manually using `debug_writeBlockProfile`.
|
||||
|
||||
|
@ -42,7 +42,7 @@ Turns on block profiling for the given duration and writes profile data to disk.
|
|||
| Console | `debug.blockProfile(file, seconds)` |
|
||||
| RPC | `{"method": "debug_blockProfile", "params": [string, number]}` |
|
||||
|
||||
## debug_chaindbCompact
|
||||
### debug_chaindbCompact
|
||||
|
||||
Flattens the entire key-value database into a single level, removing all unused slots and merging all keys.
|
||||
|
||||
|
@ -51,7 +51,7 @@ Flattens the entire key-value database into a single level, removing all unused
|
|||
| Console | `debug.chaindbCompact()` |
|
||||
| RPC | `{"method": "debug_chaindbCompact", "params": []}` |
|
||||
|
||||
## debug_chaindbProperty
|
||||
### debug_chaindbProperty
|
||||
|
||||
Returns leveldb properties of the key-value database.
|
||||
|
||||
|
@ -60,7 +60,7 @@ Returns leveldb properties of the key-value database.
|
|||
| Console | `debug.chaindbProperty(property string)` |
|
||||
| RPC | `{"method": "debug_chaindbProperty", "params": [property]}` |
|
||||
|
||||
## debug_cpuProfile
|
||||
### debug_cpuProfile
|
||||
|
||||
Turns on CPU profiling for the given duration and writes profile data to disk.
|
||||
|
||||
|
@ -69,7 +69,7 @@ Turns on CPU profiling for the given duration and writes profile data to disk.
|
|||
| Console | `debug.cpuProfile(file, seconds)` |
|
||||
| RPC | `{"method": "debug_cpuProfile", "params": [string, number]}` |
|
||||
|
||||
## debug_dbAncient
|
||||
### debug_dbAncient
|
||||
|
||||
Retrieves an ancient binary blob from the freezer. The freezer is a collection of append-only immutable files. The first argument `kind` specifies which table to look up data from. The list of all table kinds are as follows:
|
||||
|
||||
|
@ -84,7 +84,7 @@ Retrieves an ancient binary blob from the freezer. The freezer is a collection o
|
|||
| Console | `debug.dbAncient(kind string, number uint64)` |
|
||||
| RPC | `{"method": "debug_dbAncient", "params": [string, number]}` |
|
||||
|
||||
## debug_dbAncients
|
||||
### debug_dbAncients
|
||||
|
||||
Returns the number of ancient items in the ancient store.
|
||||
|
||||
|
@ -93,7 +93,7 @@ Returns the number of ancient items in the ancient store.
|
|||
| Console | `debug.dbAncients()` |
|
||||
| RPC | `{"method": "debug_dbAncients"}` |
|
||||
|
||||
## debug_dbGet
|
||||
### debug_dbGet
|
||||
|
||||
Returns the raw value of a key stored in the database.
|
||||
|
||||
|
@ -102,7 +102,7 @@ Returns the raw value of a key stored in the database.
|
|||
| Console | `debug.dbGet(key string)` |
|
||||
| RPC | `{"method": "debug_dbGet", "params": [key]}` |
|
||||
|
||||
## debug_dumpBlock
|
||||
### debug_dumpBlock
|
||||
|
||||
Retrieves the state that corresponds to the block number and returns a list of accounts (including storage and code).
|
||||
|
||||
|
@ -112,7 +112,7 @@ Retrieves the state that corresponds to the block number and returns a list of a
|
|||
| Console | `debug.traceBlockByHash(number, [options])` |
|
||||
| RPC | `{"method": "debug_dumpBlock", "params": [number]}` |
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
```javascript
|
||||
> debug.dumpBlock(10)
|
||||
|
@ -138,7 +138,7 @@ Retrieves the state that corresponds to the block number and returns a list of a
|
|||
}
|
||||
```
|
||||
|
||||
## debug_freeOSMemory
|
||||
### debug_freeOSMemory
|
||||
|
||||
Forces garbage collection
|
||||
|
||||
|
@ -148,7 +148,7 @@ Forces garbage collection
|
|||
| Console | `debug.freeOSMemory()` |
|
||||
| RPC | `{"method": "debug_freeOSMemory", "params": []}` |
|
||||
|
||||
## debug_freezeClient
|
||||
### debug_freezeClient
|
||||
|
||||
Forces a temporary client freeze, normally when the server is overloaded. Available as part of LES light server.
|
||||
|
||||
|
@ -157,7 +157,7 @@ Forces a temporary client freeze, normally when the server is overloaded. Availa
|
|||
| Console | `debug.freezeClient(node string)` |
|
||||
| RPC | `{"method": "debug_freezeClient", "params": [node]}` |
|
||||
|
||||
## debug_gcStats
|
||||
### debug_gcStats
|
||||
|
||||
Returns garbage collection statistics.
|
||||
|
||||
|
@ -168,16 +168,19 @@ See https://golang.org/pkg/runtime/debug/#GCStats for information about the fiel
|
|||
| Console | `debug.gcStats()` |
|
||||
| RPC | `{"method": "debug_gcStats", "params": []}` |
|
||||
|
||||
## debug_getAccessibleState
|
||||
### debug_getAccessibleState
|
||||
|
||||
Returns the first number where the node has accessible state on disk. This is the post-state of that block and the pre-state of the next block. The (from, to) parameters are the sequence of blocks to search, which can go either forwards or backwards.
|
||||
Returns the first number where the node has accessible state on disk. This is the post-state of that block and the pre-state of the next
|
||||
block. The (from, to) parameters are the sequence of blocks to search, which can go either forwards or backwards.
|
||||
|
||||
Note: to get the last state pass in the range of blocks in reverse, i.e. (last, first).
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | -------------------------------------------------------------- |
|
||||
| Console | `debug.getAccessibleState(from, to rpc.BlockNumber)` |
|
||||
| RPC | `{"method": "debug_getAccessibleState", "params": [from, to]}` |
|
||||
|
||||
## debug_getBadBlocks
|
||||
### debug_getBadBlocks
|
||||
|
||||
Returns a list of the last 'bad blocks' that the client has seen on the network and returns them as a JSON list of block-hashes.
|
||||
|
||||
|
@ -186,7 +189,7 @@ Returns a list of the last 'bad blocks' that the client has seen on the network
|
|||
| Console | `debug.getBadBlocks()` |
|
||||
| RPC | `{"method": "debug_getBadBlocks", "params": []}` |
|
||||
|
||||
## debug_getBlockRlp
|
||||
### debug_getBlockRlp
|
||||
|
||||
Retrieves and returns the RLP encoded block by number.
|
||||
|
||||
|
@ -196,9 +199,9 @@ Retrieves and returns the RLP encoded block by number.
|
|||
| Console | `debug.getBlockRlp(number, [options])` |
|
||||
| RPC | `{"method": "debug_getBlockRlp", "params": [number]}` |
|
||||
|
||||
References: [RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/#top)
|
||||
References: [RLP](https://github.com/ethereum/wiki/wiki/RLP)
|
||||
|
||||
## debug_getHeaderRlp
|
||||
### debug_getHeaderRlp
|
||||
|
||||
Returns an RLP-encoded header.
|
||||
|
||||
|
@ -207,7 +210,7 @@ Returns an RLP-encoded header.
|
|||
| Console | `debug.getHeaderRlp(blockNum)` |
|
||||
| RPC | `{"method": "debug_getHeaderRlp", "params": [num]}` |
|
||||
|
||||
## debug_getModifiedAccountsByHash
|
||||
### debug_getModifiedAccountsByHash
|
||||
|
||||
Returns all accounts that have changed between the two blocks specified. A change is defined as a difference in nonce, balance, code hash, or storage hash. With one parameter, returns the list of accounts modified in the specified block.
|
||||
|
||||
|
@ -216,16 +219,17 @@ Returns all accounts that have changed between the two blocks specified. A chang
|
|||
| Console | `debug.getModifiedAccountsByHash(startHash, endHash)` |
|
||||
| RPC | `{"method": "debug_getModifiedAccountsByHash", "params": [startHash, endHash]}` |
|
||||
|
||||
## debug_getModifiedAccountsByNumber
|
||||
### debug_getModifiedAccountsByNumber
|
||||
|
||||
Returns all accounts that have changed between the two blocks specified. A change is defined as a difference in nonce, balance, code hash or storage hash.
|
||||
Returns all accounts that have changed between the two blocks specified. A change is defined as a difference in nonce, balance, code hash or
|
||||
storage hash.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | ------------------------------------------------------------------------------- |
|
||||
| Console | `debug.getModifiedAccountsByNumber(startNum uint64, endNum uint64)` |
|
||||
| RPC | `{"method": "debug_getModifiedAccountsByNumber", "params": [startNum, endNum]}` |
|
||||
|
||||
## debug_getRawReceipts
|
||||
### debug_getRawReceipts
|
||||
|
||||
Returns the consensus-encoding of all receipts in a single block.
|
||||
|
||||
|
@ -234,7 +238,7 @@ Returns the consensus-encoding of all receipts in a single block.
|
|||
| Console | `debug.getRawReceipts(blockNrOrHash)` |
|
||||
| RPC | `{"method": "debug_getRawReceipts", "params": [blockNrOrHash]}` |
|
||||
|
||||
## debug_goTrace
|
||||
### debug_goTrace
|
||||
|
||||
Turns on Go runtime tracing for the given duration and writes trace data to disk.
|
||||
|
||||
|
@ -243,7 +247,7 @@ Turns on Go runtime tracing for the given duration and writes trace data to disk
|
|||
| Console | `debug.goTrace(file, seconds)` |
|
||||
| RPC | `{"method": "debug_goTrace", "params": [string, number]}` |
|
||||
|
||||
## debug_intermediateRoots
|
||||
### debug_intermediateRoots
|
||||
|
||||
Executes a block (bad- or canon- or side-), and returns a list of intermediate roots: the stateroot after each transaction.
|
||||
|
||||
|
@ -252,7 +256,7 @@ Executes a block (bad- or canon- or side-), and returns a list of intermediate r
|
|||
| Console | `debug.intermediateRoots(blockHash, [options])` |
|
||||
| RPC | `{"method": "debug_intermediateRoots", "params": [blockHash, {}]}` |
|
||||
|
||||
## debug_memStats
|
||||
### debug_memStats
|
||||
|
||||
Returns detailed runtime memory statistics.
|
||||
|
||||
|
@ -263,7 +267,7 @@ See https://golang.org/pkg/runtime/#MemStats for information about the fields of
|
|||
| Console | `debug.memStats()` |
|
||||
| RPC | `{"method": "debug_memStats", "params": []}` |
|
||||
|
||||
## debug_mutexProfile
|
||||
### debug_mutexProfile
|
||||
|
||||
Turns on mutex profiling for nsec seconds and writes profile data to file. It uses a profile rate of 1 for most accurate information. If a different rate is desired, set the rate and write the profile manually.
|
||||
|
||||
|
@ -272,7 +276,7 @@ Turns on mutex profiling for nsec seconds and writes profile data to file. It us
|
|||
| Console | `debug.mutexProfile(file, nsec)` |
|
||||
| RPC | `{"method": "debug_mutexProfile", "params": [file, nsec]}` |
|
||||
|
||||
## debug_preimage
|
||||
### debug_preimage
|
||||
|
||||
Returns the preimage for a sha3 hash, if known.
|
||||
|
||||
|
@ -281,7 +285,7 @@ Returns the preimage for a sha3 hash, if known.
|
|||
| Console | `debug.preimage(hash)` |
|
||||
| RPC | `{"method": "debug_preimage", "params": [hash]}` |
|
||||
|
||||
## debug_printBlock
|
||||
### debug_printBlock
|
||||
|
||||
Retrieves a block and returns its pretty printed form.
|
||||
|
||||
|
@ -290,7 +294,7 @@ Retrieves a block and returns its pretty printed form.
|
|||
| Console | `debug.printBlock(number uint64)` |
|
||||
| RPC | `{"method": "debug_printBlock", "params": [number]}` |
|
||||
|
||||
## debug_seedHash
|
||||
### debug_seedHash
|
||||
|
||||
Fetches and retrieves the seed hash of the block by number
|
||||
|
||||
|
@ -300,7 +304,7 @@ Fetches and retrieves the seed hash of the block by number
|
|||
| Console | `debug.seedHash(number, [options])` |
|
||||
| RPC | `{"method": "debug_seedHash", "params": [number]}` |
|
||||
|
||||
## debug_setBlockProfileRate
|
||||
### debug_setBlockProfileRate
|
||||
|
||||
Sets the rate (in samples/sec) of goroutine block profile data collection. A non-zero rate enables block profiling, setting it to zero stops the profile. Collected profile data can be written using `debug_writeBlockProfile`.
|
||||
|
||||
|
@ -309,7 +313,7 @@ Sets the rate (in samples/sec) of goroutine block profile data collection. A non
|
|||
| Console | `debug.setBlockProfileRate(rate)` |
|
||||
| RPC | `{"method": "debug_setBlockProfileRate", "params": [number]}` |
|
||||
|
||||
## debug_setGCPercent
|
||||
### debug_setGCPercent
|
||||
|
||||
Sets the garbage collection target percentage. A negative value disables garbage collection.
|
||||
|
||||
|
@ -319,9 +323,9 @@ Sets the garbage collection target percentage. A negative value disables garbage
|
|||
| Console | `debug.setGCPercent(v)` |
|
||||
| RPC | `{"method": "debug_setGCPercent", "params": [v]}` |
|
||||
|
||||
## debug_setHead
|
||||
### debug_setHead
|
||||
|
||||
Sets the current head of the local chain by block number. **Note**, this is a destructive action and may severely damage the chain. Use with _extreme_ caution.
|
||||
Sets the current head of the local chain by block number. **Note**, this is a destructive action and may severely damage your chain. Use with _extreme_ caution.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | ------------------------------------------------- |
|
||||
|
@ -330,9 +334,9 @@ Sets the current head of the local chain by block number. **Note**, this is a de
|
|||
| RPC | `{"method": "debug_setHead", "params": [number]}` |
|
||||
|
||||
References:
|
||||
[Ethash](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/mining-algorithms/ethash)
|
||||
[Ethash](https://eth.wiki/en/concepts/ethash/ethash)
|
||||
|
||||
## debug_setMutexProfileFraction
|
||||
### debug_setMutexProfileFraction
|
||||
|
||||
Sets the rate of mutex profiling.
|
||||
|
||||
|
@ -341,7 +345,7 @@ Sets the rate of mutex profiling.
|
|||
| Console | `debug.setMutexProfileFraction(rate int)` |
|
||||
| RPC | `{"method": "debug_setMutexProfileFraction", "params": [rate]}` |
|
||||
|
||||
## debug_stacks
|
||||
### debug_stacks
|
||||
|
||||
Returns a printed representation of the stacks of all goroutines. Note that the web3 wrapper for this method takes care of the printing and does not return the string.
|
||||
|
||||
|
@ -350,7 +354,7 @@ Returns a printed representation of the stacks of all goroutines. Note that the
|
|||
| Console | `debug.stacks()` |
|
||||
| RPC | `{"method": "debug_stacks", "params": []}` |
|
||||
|
||||
## debug_standardTraceBlockToFile
|
||||
### debug_standardTraceBlockToFile
|
||||
|
||||
When JS-based tracing (see below) was first implemented, the intended usecase was to enable long-running tracers that could stream results back via a subscription channel. This method works a bit differently. (For full details, see [PR](https://github.com/ethereum/go-ethereum/pull/17914))
|
||||
|
||||
|
@ -365,14 +369,14 @@ This means that this method is only 'useful' for callers who control the node --
|
|||
|
||||
The method can be used to dump a certain transaction out of a given block:
|
||||
|
||||
```sh
|
||||
```
|
||||
> debug.standardTraceBlockToFile("0x0bbe9f1484668a2bf159c63f0cf556ed8c8282f99e3ffdb03ad2175a863bca63", {txHash:"0x4049f61ffbb0747bb88dc1c85dd6686ebf225a3c10c282c45a8e0c644739f7e9", disableMemory:true})
|
||||
["/tmp/block_0x0bbe9f14-14-0x4049f61f-099048234"]
|
||||
```
|
||||
|
||||
Or all txs from a block:
|
||||
|
||||
```sh
|
||||
```
|
||||
> debug.standardTraceBlockToFile("0x0bbe9f1484668a2bf159c63f0cf556ed8c8282f99e3ffdb03ad2175a863bca63", {disableMemory:true})
|
||||
["/tmp/block_0x0bbe9f14-0-0xb4502ea7-409046657", "/tmp/block_0x0bbe9f14-1-0xe839be8f-954614764", "/tmp/block_0x0bbe9f14-2-0xc6e2052f-542255195", "/tmp/block_0x0bbe9f14-3-0x01b7f3fe-209673214", "/tmp/block_0x0bbe9f14-4-0x0f290422-320999749", "/tmp/block_0x0bbe9f14-5-0x2dc0fb80-844117472", "/tmp/block_0x0bbe9f14-6-0x35542da1-256306111", "/tmp/block_0x0bbe9f14-7-0x3e199a08-086370834", "/tmp/block_0x0bbe9f14-8-0x87778b88-194603593", "/tmp/block_0x0bbe9f14-9-0xbcb081ba-629580052", "/tmp/block_0x0bbe9f14-10-0xc254381a-578605923", "/tmp/block_0x0bbe9f14-11-0xcc434d58-405931366", "/tmp/block_0x0bbe9f14-12-0xce61967d-874423181", "/tmp/block_0x0bbe9f14-13-0x05a20b35-267153288", "/tmp/block_0x0bbe9f14-14-0x4049f61f-606653767", "/tmp/block_0x0bbe9f14-15-0x46d473d2-614457338", "/tmp/block_0x0bbe9f14-16-0x35cf5500-411906321", "/tmp/block_0x0bbe9f14-17-0x79222961-278569788", "/tmp/block_0x0bbe9f14-18-0xad84e7b1-095032683", "/tmp/block_0x0bbe9f14-19-0x4bd48260-019097038", "/tmp/block_0x0bbe9f14-20-0x1517411d-292624085", "/tmp/block_0x0bbe9f14-21-0x6857e350-971385904", "/tmp/block_0x0bbe9f14-22-0xbe3ae2ca-236639695"]
|
||||
|
||||
|
@ -393,7 +397,7 @@ INFO [10-15|13:48:34.421] Wrote trace file=/tmp/block_0x14490c57-2-0x3f4263fe-05
|
|||
|
||||
The `options` is as follows:
|
||||
|
||||
```sh
|
||||
```
|
||||
type StdTraceConfig struct {
|
||||
*vm.LogConfig
|
||||
Reexec *uint64
|
||||
|
@ -401,11 +405,11 @@ type StdTraceConfig struct {
|
|||
}
|
||||
```
|
||||
|
||||
## debug_standardTraceBadBlockToFile
|
||||
### debug_standardTraceBadBlockToFile
|
||||
|
||||
This method is similar to `debug_standardTraceBlockToFile`, but can be used to obtain info about a block which has been _rejected_ as invalid (for some reason).
|
||||
|
||||
## debug_startCPUProfile
|
||||
### debug_startCPUProfile
|
||||
|
||||
Turns on CPU profiling indefinitely, writing to the given file.
|
||||
|
||||
|
@ -414,7 +418,7 @@ Turns on CPU profiling indefinitely, writing to the given file.
|
|||
| Console | `debug.startCPUProfile(file)` |
|
||||
| RPC | `{"method": "debug_startCPUProfile", "params": [string]}` |
|
||||
|
||||
## debug_startGoTrace
|
||||
### debug_startGoTrace
|
||||
|
||||
Starts writing a Go runtime trace to the given file.
|
||||
|
||||
|
@ -423,7 +427,7 @@ Starts writing a Go runtime trace to the given file.
|
|||
| Console | `debug.startGoTrace(file)` |
|
||||
| RPC | `{"method": "debug_startGoTrace", "params": [string]}` |
|
||||
|
||||
## debug_stopCPUProfile
|
||||
### debug_stopCPUProfile
|
||||
|
||||
Stops an ongoing CPU profile.
|
||||
|
||||
|
@ -432,7 +436,7 @@ Stops an ongoing CPU profile.
|
|||
| Console | `debug.stopCPUProfile()` |
|
||||
| RPC | `{"method": "debug_stopCPUProfile", "params": []}` |
|
||||
|
||||
## debug_stopGoTrace
|
||||
### debug_stopGoTrace
|
||||
|
||||
Stops writing the Go runtime trace.
|
||||
|
||||
|
@ -441,7 +445,7 @@ Stops writing the Go runtime trace.
|
|||
| Console | `debug.startGoTrace(file)` |
|
||||
| RPC | `{"method": "debug_stopGoTrace", "params": []}` |
|
||||
|
||||
## debug_storageRangeAt
|
||||
### debug_storageRangeAt
|
||||
|
||||
Returns the storage at the given block height and transaction index. The result can be paged by providing a `maxResult` to cap the number of storage slots returned as well as specifying the offset via `keyStart` (hash of storage key).
|
||||
|
||||
|
@ -450,29 +454,30 @@ Returns the storage at the given block height and transaction index. The result
|
|||
| Console | `debug.storageRangeAt(blockHash, txIdx, contractAddress, keyStart, maxResult)` |
|
||||
| RPC | `{"method": "debug_storageRangeAt", "params": [blockHash, txIdx, contractAddress, keyStart, maxResult]}` |
|
||||
|
||||
## debug_traceBadBlock
|
||||
### debug_traceBadBlock
|
||||
|
||||
Returns the structured logs created during the execution of EVM against a block pulled from the pool of bad ones and returns them as a JSON object.
|
||||
For the second parameter see [TraceConfig](#traceconfig) reference.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | -------------------------------------------------------------- |
|
||||
| Console | `debug.traceBadBlock(blockHash, [options])` |
|
||||
| RPC | `{"method": "debug_traceBadBlock", "params": [blockHash, {}]}` |
|
||||
|
||||
## debug_traceBlock
|
||||
### debug_traceBlock
|
||||
|
||||
The `traceBlock` method will return a full stack trace of all invoked opcodes of all transaction that were included in this block. **Note**, the parent of this block must be present or it will fail.
|
||||
The `traceBlock` method will return a full stack trace of all invoked opcodes of all transaction that were included in this block. **Note**, the parent of this block must be present or it will fail. For the second parameter see [TraceConfig](#traceconfig) reference.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | ------------------------------------------------------------------------ |
|
||||
| Go | `debug.TraceBlock(blockRlp []byte, config. *vm.Config) BlockTraceResult` |
|
||||
| Console | `debug.traceBlock(tblockRlp, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlock", "params": [blockRlp, {}]}` |
|
||||
| Client | Method invocation |
|
||||
| :------ | ------------------------------------------------------------------------- |
|
||||
| Go | `debug.TraceBlock(blockRlp []byte, config *TraceConfig) BlockTraceResult` |
|
||||
| Console | `debug.traceBlock(tblockRlp, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlock", "params": [blockRlp, {}]}` |
|
||||
|
||||
References:
|
||||
[RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)
|
||||
[RLP](https://github.com/ethereum/wiki/wiki/RLP)
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
```javascript
|
||||
> debug.traceBlock("0xblock_rlp")
|
||||
|
@ -508,48 +513,48 @@ References:
|
|||
}]
|
||||
```
|
||||
|
||||
## debug_traceBlockByNumber
|
||||
### debug_traceBlockByNumber
|
||||
|
||||
Similar to [debug_traceBlock](#debug_traceblock), `traceBlockByNumber` accepts a block number and will replay the block that is already present in the database.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | ------------------------------------------------------------------------------ |
|
||||
| Go | `debug.TraceBlockByNumber(number uint64, config. *vm.Config) BlockTraceResult` |
|
||||
| Console | `debug.traceBlockByNumber(number, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlockByNumber", "params": [number, {}]}` |
|
||||
|
||||
References:
|
||||
[RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)
|
||||
|
||||
## debug_traceBlockByHash
|
||||
|
||||
Similar to [debug_traceBlock](#debug_traceblock), `traceBlockByHash` accepts a block hash and will replay the block that is already present in the database.
|
||||
Similar to [debug_traceBlock](#debug_traceblock), `traceBlockByNumber` accepts a block number and will replay the block that is already present in the database. For the second parameter see [TraceConfig](#traceconfig) reference.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | ------------------------------------------------------------------------------- |
|
||||
| Go | `debug.TraceBlockByHash(hash common.Hash, config. *vm.Config) BlockTraceResult` |
|
||||
| Console | `debug.traceBlockByHash(hash, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlockByHash", "params": [hash {}]}` |
|
||||
| Go | `debug.TraceBlockByNumber(number uint64, config *TraceConfig) BlockTraceResult` |
|
||||
| Console | `debug.traceBlockByNumber(number, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlockByNumber", "params": [number, {}]}` |
|
||||
|
||||
References:
|
||||
[RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)
|
||||
[RLP](https://github.com/ethereum/wiki/wiki/RLP)
|
||||
|
||||
## debug_traceBlockFromFile
|
||||
### debug_traceBlockByHash
|
||||
|
||||
Similar to [debug_traceBlock](#debug_traceblock), `traceBlockFromFile` accepts a file containing the RLP of the block.
|
||||
Similar to [debug_traceBlock](#debug_traceblock), `traceBlockByHash` accepts a block hash and will replay the block that is already present in the database. For the second parameter see [TraceConfig](#traceconfig) reference.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | -------------------------------------------------------------------------------- |
|
||||
| Go | `debug.TraceBlockFromFile(fileName string, config. *vm.Config) BlockTraceResult` |
|
||||
| Console | `debug.traceBlockFromFile(fileName, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlockFromFile", "params": [fileName, {}]}` |
|
||||
| Go | `debug.TraceBlockByHash(hash common.Hash, config *TraceConfig) BlockTraceResult` |
|
||||
| Console | `debug.traceBlockByHash(hash, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlockByHash", "params": [hash {}]}` |
|
||||
|
||||
References:
|
||||
[RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)
|
||||
[RLP](https://github.com/ethereum/wiki/wiki/RLP)
|
||||
|
||||
## debug_traceCall
|
||||
### debug_traceBlockFromFile
|
||||
|
||||
The `debug_traceCall` method enables running an `eth_call` within the context of the given block execution using the final state of parent block as the base. The first argument (just as in `eth_call`) is a [transaction object](/docs/rpc/objects#transaction-call-object). The block can be specified either by hash or by number as the second argument. A tracer can be specified as a third argument, similar to `debug_traceTransaction`. It returns the same output as `debug_traceTransaction`.
|
||||
Similar to [debug_traceBlock](#debug_traceblock), `traceBlockFromFile` accepts a file containing the RLP of the block. For the second parameter see [TraceConfig](#traceconfig) reference.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | --------------------------------------------------------------------------------- |
|
||||
| Go | `debug.TraceBlockFromFile(fileName string, config *TraceConfig) BlockTraceResult` |
|
||||
| Console | `debug.traceBlockFromFile(fileName, [options])` |
|
||||
| RPC | `{"method": "debug_traceBlockFromFile", "params": [fileName, {}]}` |
|
||||
|
||||
References:
|
||||
[RLP](https://github.com/ethereum/wiki/wiki/RLP)
|
||||
|
||||
### debug_traceCall
|
||||
|
||||
The `debug_traceCall` method lets you run an `eth_call` within the context of the given block execution using the final state of parent block as the base. The first argument (just as in `eth_call`) is a [transaction object](/docs/rpc/objects#transaction-call-object). The block can be specified either by hash or by number as the second argument. The trace can be configured similar to `debug_traceTransaction`, see [TraceConfig](#traceconfig). The method returns the same output as `debug_traceTransaction`.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :-----: | --------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
@ -557,7 +562,7 @@ The `debug_traceCall` method enables running an `eth_call` within the context of
|
|||
| Console | `debug.traceCall(object, blockNrOrHash, [options])` |
|
||||
| RPC | `{"method": "debug_traceCall", "params": [object, blockNrOrHash, {}]}` |
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
No specific call options:
|
||||
|
||||
|
@ -625,39 +630,50 @@ Curl example:
|
|||
{"jsonrpc":"2.0","id":1,"result":{"gas":53000,"failed":false,"returnValue":"","structLogs":[]}}
|
||||
```
|
||||
|
||||
## debug_traceChain
|
||||
### debug_traceChain
|
||||
|
||||
Returns the structured logs created during the execution of EVM between two blocks (excluding start) as a JSON object. This endpoint must be invoked via `debug_subscribe` as follows:
|
||||
|
||||
`const res = provider.send('debug_subscribe', ['traceChain', '0x3f3a2a', '0x3f3a2b'])`
|
||||
```js
|
||||
const res = provider.send('debug_subscribe', ['traceChain', '0x3f3a2a', '0x3f3a2b'])`
|
||||
```
|
||||
|
||||
please refer to the [subscription page](/docs/rpc/pubsub) for more details.
|
||||
please refer to the [subscription page](https://geth.ethereum.org/docs/rpc/pubsub) for more details.
|
||||
|
||||
## debug_traceTransaction
|
||||
### debug_traceTransaction
|
||||
|
||||
**OBS** In most scenarios, `debug.standardTraceBlockToFile` is better suited for tracing!
|
||||
|
||||
The `traceTransaction` debugging method will attempt to run the transaction in the exact same manner as it was executed on the network. It will replay any transaction that may have been executed prior to this one before it will finally attempt to execute the transaction that corresponds to the given
|
||||
hash.
|
||||
|
||||
In addition to the hash of the transaction it can take a secondary _optional_ argument, which specifies the options for this specific call. The possible options are:
|
||||
| Client | Method invocation |
|
||||
| :------ | ------------------------------------------------------------------------------------------- |
|
||||
| Go | `debug.TraceTransaction(txHash common.Hash, config *TraceConfig) (*ExecutionResult, error)` |
|
||||
| Console | `debug.traceTransaction(txHash, [options])` |
|
||||
| RPC | `{"method": "debug_traceTransaction", "params": [txHash, {}]}` |
|
||||
|
||||
#### TraceConfig
|
||||
|
||||
In addition to the hash of the transaction you may give it a secondary _optional_ argument, which specifies the options for this specific call. The possible options are:
|
||||
|
||||
- `disableStorage`: `BOOL`. Setting this to true will disable storage capture (default = false).
|
||||
- `disableStack`: `BOOL`. Setting this to true will disable stack capture (default = false).
|
||||
- `enableMemory`: `BOOL`. Setting this to true will enable memory capture (default = false).
|
||||
- `enableReturnData`: `BOOL`. Setting this to true will enable return data capture (default = false).
|
||||
- `tracer`: `STRING`. Setting this will enable JavaScript-based transaction tracing, described below. If set, the previous four arguments will be ignored.
|
||||
- `timeout`: `STRING`. Overrides the default timeout of 5 seconds for JavaScript-based tracing calls. Valid values are described [here](https://golang.org/pkg/time/#ParseDuration).
|
||||
- `tracer`: `STRING`. Name for built-in tracer or Javascript expression. See below for more details.
|
||||
|
||||
| Client | Method invocation |
|
||||
| :------ | -------------------------------------------------------------------------------------------- |
|
||||
| Go | `debug.TraceTransaction(txHash common.Hash, logger *vm.LogConfig) (*ExecutionResult, error)` |
|
||||
| Console | `debug.traceTransaction(txHash, [options])` |
|
||||
| RPC | `{"method": "debug_traceTransaction", "params": [txHash, {}]}` |
|
||||
If set, the previous four arguments will be ignored.
|
||||
|
||||
### Example
|
||||
- `timeout`: `STRING`. Overrides the default timeout of 5 seconds for JavaScript-based tracing calls.
|
||||
Valid values are described [here](https://golang.org/pkg/time/#ParseDuration).
|
||||
- `tracerConfig`: Config for the specified `tracer`. For example see callTracer's [config](/docs/evm-tracing/builtin-tracers#config).
|
||||
|
||||
```javascript
|
||||
Geth comes with a bundle of [built-in tracers](/docs/evm-tracing/builtin-tracers), each providing various data about a transaction. This method defaults to the [struct logger](/docs/evm-tracing/builtin-tracers#structopcode-logger). The `tracer` field of the second parameter can be set to use any of the other tracers. Alternatively a [custom tracer](/docs/evm-tracing/custom-tracer) can be implemented in either Go or Javascript.
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
> debug.traceTransaction("0x2059dd53ecac9827faad14d364f9e04b1d5fe5b506e3acc886eff7a6f88a696a")
|
||||
{
|
||||
gas: 85301,
|
||||
|
@ -691,128 +707,7 @@ In addition to the hash of the transaction it can take a secondary _optional_ ar
|
|||
}]
|
||||
```
|
||||
|
||||
### JavaScript-based tracing
|
||||
|
||||
Specifying the `tracer` option in the second argument enables JavaScript-based tracing. In this mode, `tracer` is interpreted as a JavaScript expression that is expected to evaluate to an object which must expose the `result` and `fault` methods. There exist 3 additional methods, namely: `step`, `enter` and `exit`. One of either `step`, or `enter` AND `exit` must be provided(i.e. `enter` and `exit` must be exposed together). All three can be provided together.
|
||||
|
||||
#### Step
|
||||
|
||||
`step`is a function that takes two arguments, log and db, and is called for each step of the EVM, or when an error occurs, as the specified transaction is traced.
|
||||
|
||||
`log` has the following fields:
|
||||
|
||||
- `op`: Object, an OpCode object representing the current opcode
|
||||
- `stack`: Object, a structure representing the EVM execution stack
|
||||
- `memory`: Object, a structure representing the contract's memory space
|
||||
- `contract`: Object, an object representing the account executing the current operation
|
||||
|
||||
and the following methods:
|
||||
|
||||
- `getPC()` - returns a Number with the current program counter
|
||||
- `getGas()` - returns a Number with the amount of gas remaining
|
||||
- `getCost()` - returns the cost of the opcode as a Number
|
||||
- `getDepth()` - returns the execution depth as a Number
|
||||
- `getRefund()` - returns the amount to be refunded as a Number
|
||||
- `getError()` - returns information about the error if one occured, otherwise returns `undefined`
|
||||
|
||||
If error is non-empty, all other fields should be ignored.
|
||||
|
||||
For efficiency, the same `log` object is reused on each execution step, updated with current values; make sure to copy values that are needed beyond the current call. For instance, this step function will not work:
|
||||
|
||||
function(log) {
|
||||
this.logs.append(log);
|
||||
}
|
||||
|
||||
But this step function will:
|
||||
|
||||
function(log) {
|
||||
this.logs.append({gas: log.getGas(), pc: log.getPC(), ...});
|
||||
}
|
||||
|
||||
`log.op` has the following methods:
|
||||
|
||||
- `isPush()` - returns true iff the opcode is a PUSHn
|
||||
- `toString()` - returns the string representation of the opcode
|
||||
- `toNumber()` - returns the opcode's number
|
||||
|
||||
`log.memory` has the following methods:
|
||||
|
||||
- `slice(start, stop)` - returns the specified segment of memory as a byte slice
|
||||
- `getUint(offset)` - returns the 32 bytes at the given offset
|
||||
|
||||
`log.stack` has the following methods:
|
||||
|
||||
- `peek(idx)` - returns the idx-th element from the top of the stack (0 is the topmost element) as a big.Int
|
||||
- `length()` - returns the number of elements in the stack
|
||||
|
||||
`log.contract` has the following methods:
|
||||
|
||||
- `getCaller()` - returns the address of the caller
|
||||
- `getAddress()` - returns the address of the current contract
|
||||
- `getValue()` - returns the amount of value sent from caller to contract as a big.Int
|
||||
- `getInput()` - returns the input data passed to the contract
|
||||
|
||||
`db` has the following methods:
|
||||
|
||||
- `getBalance(address)` - returns a `big.Int` with the specified account's balance
|
||||
- `getNonce(address)` - returns a Number with the specified account's nonce
|
||||
- `getCode(address)` - returns a byte slice with the code for the specified account
|
||||
- `getState(address, hash)` - returns the state value for the specified account and the specified hash
|
||||
- `exists(address)` - returns true if the specified address exists
|
||||
|
||||
If the step function throws an exception or executes an illegal operation at any point, it will not be called on any further VM steps, and the error will be returned to the caller.
|
||||
|
||||
#### Result
|
||||
|
||||
`result` is a function that takes two arguments `ctx` and `db`, and is expected to return a JSON-serializable value to return to the RPC caller.
|
||||
|
||||
`ctx` is the context in which the transaction is executing and has the following fields:
|
||||
|
||||
- `type` - String, one of the two values `CALL` and `CREATE`
|
||||
- `from` - Address, sender of the transaction
|
||||
- `to` - Address, target of the transaction
|
||||
- `input` - Buffer, input transaction data
|
||||
- `gas` - Number, gas budget of the transaction
|
||||
- `value` - big.Int, amount to be transferred in wei
|
||||
- `block` - Number, block number
|
||||
- `output` - Buffer, value returned from EVM
|
||||
- `gasUsed` - Number, amount of gas used in executing the transaction (excludes txdata costs)
|
||||
- `time` - String, execution runtime
|
||||
|
||||
#### Fault
|
||||
|
||||
`fault` is a function that takes two arguments, `log` and `db`, just like `step` and is invoked when an error happens during the execution of an opcode which wasn't reported in `step`. The method `log.getError()` has information about the error.
|
||||
|
||||
#### Enter & Exit
|
||||
|
||||
`enter` and `exit` are respectively invoked on stepping in and out of an internal call. More specifically they are invoked on the `CALL` variants, `CREATE` variants and also for the transfer implied by a `SELFDESTRUCT`.
|
||||
|
||||
`enter` takes a `callFrame` object as argument which has the following methods:
|
||||
|
||||
- `getType()` - returns a string which has the type of the call frame
|
||||
- `getFrom()` - returns the address of the call frame sender
|
||||
- `getTo()` - returns the address of the call frame target
|
||||
- `getInput()` - returns the input as a buffer
|
||||
- `getGas()` - returns a Number which has the amount of gas provided for the frame
|
||||
- `getValue()` - returns a `big.Int` with the amount to be transferred only if available, otherwise `undefined`
|
||||
|
||||
`exit` takes in a `frameResult` object which has the following methods:
|
||||
|
||||
- `getGasUsed()` - returns amount of gas used throughout the frame as a Number
|
||||
- `getOutput()` - returns the output as a buffer
|
||||
` -getError()` - returns an error if one occured during execution and `undefined` otherwise
|
||||
|
||||
#### Usage
|
||||
|
||||
Note that several values are Golang big.Int objects, not JavaScript numbers or JS bigints. As such, they have the same interface as described in the godocs. Their default serialization to JSON is as a Javascript number; to serialize large numbers accurately call `.String()` on them. For convenience, `big.NewInt(x)` is provided, and will convert a uint to a Go BigInt.
|
||||
|
||||
Usage example, returns the top element of the stack at each CALL opcode only:
|
||||
|
||||
```sh
|
||||
debug.traceTransaction(txhash, {tracer: '{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == "CALL") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}'});
|
||||
```
|
||||
|
||||
## debug_verbosity
|
||||
### debug_verbosity
|
||||
|
||||
Sets the logging verbosity ceiling. Log messages with level up to and including the given level will be printed.
|
||||
|
||||
|
@ -823,7 +718,7 @@ The verbosity of individual packages and source files can be raised using `debug
|
|||
| Console | `debug.verbosity(level)` |
|
||||
| RPC | `{"method": "debug_vmodule", "params": [number]}` |
|
||||
|
||||
## debug_vmodule
|
||||
### debug_vmodule
|
||||
|
||||
Sets the logging verbosity pattern.
|
||||
|
||||
|
@ -832,34 +727,33 @@ Sets the logging verbosity pattern.
|
|||
| Console | `debug.vmodule(string)` |
|
||||
| RPC | `{"method": "debug_vmodule", "params": [string]}` |
|
||||
|
||||
### Examples
|
||||
#### Examples
|
||||
|
||||
To see messages from a particular Go package (directory) and all subdirectories, use:
|
||||
If you want to see messages from a particular Go package (directory) and all subdirectories, use:
|
||||
|
||||
```javascript
|
||||
> debug.vmodule("eth/*=6")
|
||||
```
|
||||
|
||||
To restrict messages to a particular package (e.g. p2p)
|
||||
but exclude subdirectories, use:
|
||||
If you want to restrict messages to a particular package (e.g. p2p) but exclude subdirectories, use:
|
||||
|
||||
```javascript
|
||||
> debug.vmodule("p2p=6")
|
||||
```
|
||||
|
||||
To see log messages from a particular source file, use
|
||||
If you want to see log messages from a particular source file, use
|
||||
|
||||
```javascript
|
||||
> debug.vmodule("server.go=6")
|
||||
```
|
||||
|
||||
To see all output from peer.go in a package below eth (eth/peer.go, eth/downloader/peer.go) as well as output from package p2p at level <= 5, use:
|
||||
You can compose these basic patterns. If you want to see all output from peer.go in a package below eth (eth/peer.go, eth/downloader/peer.go) as well as output from package p2p at level <= 5, use:
|
||||
|
||||
```javascript
|
||||
debug.vmodule('eth/*/peer.go=6,p2p=5');
|
||||
```
|
||||
|
||||
## debug_writeBlockProfile
|
||||
### debug_writeBlockProfile
|
||||
|
||||
Writes a goroutine blocking profile to the given file.
|
||||
|
||||
|
@ -868,7 +762,7 @@ Writes a goroutine blocking profile to the given file.
|
|||
| Console | `debug.writeBlockProfile(file)` |
|
||||
| RPC | `{"method": "debug_writeBlockProfile", "params": [string]}` |
|
||||
|
||||
## debug_writeMemProfile
|
||||
### debug_writeMemProfile
|
||||
|
||||
Writes an allocation profile to the given file. Note that the profiling rate cannot be set through the API, it must be set on the command line using the `--pprof.memprofilerate` flag.
|
||||
|
||||
|
@ -877,7 +771,7 @@ Writes an allocation profile to the given file. Note that the profiling rate can
|
|||
| Console | `debug.writeMemProfile(file string)` |
|
||||
| RPC | `{"method": "debug_writeBlockProfile", "params": [string]}` |
|
||||
|
||||
## debug_writeMutexProfile
|
||||
### debug_writeMutexProfile
|
||||
|
||||
Writes a goroutine blocking profile to the given file.
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ description: Documentation for the JSON-RPC API "eth" namespace
|
|||
|
||||
Documentation for the API methods in the `eth` namespace can be found on [ethereum.org](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_protocolversion). Geth provides several extensions to the standard "eth" JSON-RPC namespace that are defined below.
|
||||
|
||||
### eth_subscribe, eth_unsubscribe
|
||||
### eth_subscribe, eth_unsubscribe {#eth-subscribe-unsubscribe}
|
||||
|
||||
These methods are used for real-time events through subscriptions. See the [subscription documentation](/docs/interacting_with_geth/RPC/pubsub) for more information.
|
||||
|
||||
### eth_call
|
||||
### eth_call {#eth-call}
|
||||
|
||||
Executes a new message call immediately, without creating a transaction on the block chain. The `eth_call` method can be used to query internal contract state, to execute validations coded into a contract or even to test what the effect of a transaction would be without running it live.
|
||||
|
||||
|
@ -136,7 +136,7 @@ And the result is the Ethereum ABI encoded threshold number:
|
|||
|
||||
Just for the sake of completeness, decoded the response is: `2`.
|
||||
|
||||
### eth_createAccessList
|
||||
### eth_createAccessList {#eth-createaccesslist}
|
||||
|
||||
This method creates an [EIP2930](https://eips.ethereum.org/EIPS/eip-2930) type `accessList` based on a given `Transaction`. The `accessList` contains all storage slots and addresses read and written by the transaction, except for the sender account and the precompiles. This method uses the same `transaction` call [object](/docs/rpc/objects#transaction-call-object) and `blockNumberOrTag` object as `eth_call`. An `accessList` can be used to unstuck contracts that became inaccessible due to gas cost increases.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Documentation for the JSON-RPC API "les" namespace
|
|||
|
||||
The `les` API is for managing LES server settings, including client parameters and payment settings for prioritized clients. It also provides functions to query checkpoint information in both server and client mode.
|
||||
|
||||
## les_serverInfo
|
||||
## les_serverInfo {#les-serverinfo}
|
||||
|
||||
Get information about currently connected and total/individual allowed connection capacity.
|
||||
|
||||
|
@ -29,7 +29,7 @@ Get information about currently connected and total/individual allowed connectio
|
|||
}
|
||||
```
|
||||
|
||||
## les_clientInfo
|
||||
## les_clientInfo {#les-clientinfo}
|
||||
|
||||
Get individual client information (connection, balance, pricing) on the specified list of clients or for all connected clients if the ID list is empty.
|
||||
|
||||
|
@ -101,7 +101,7 @@ Get individual client information (connection, balance, pricing) on the specifie
|
|||
}
|
||||
```
|
||||
|
||||
## les_priorityClientInfo
|
||||
## les_priorityClientInfo {#les-priorityclientinfo}
|
||||
|
||||
Get individual client information on clients with a positive balance in the specified ID range, `start` included, `stop` excluded. If `stop` is zero then results are returned until the last existing balance entry. `maxCount` limits the number of returned results. If the count limit is reached but there are more IDs in the range then the first missing ID is included in the result with an empty value assigned to it.
|
||||
|
||||
|
@ -196,7 +196,7 @@ Get individual client information on clients with a positive balance in the spec
|
|||
}
|
||||
```
|
||||
|
||||
## les_addBalance
|
||||
## les_addBalance {#les-addbalance}
|
||||
|
||||
Add signed value to the token balance of the specified client and update its `meta` tag. The balance cannot go below zero or over `2^^63-1`. The balance values before and after the update are returned. The `meta` tag can be used to store a sequence number or reference to the last processed incoming payment, token expiration info, balance in other currencies or any application-specific additional information.
|
||||
|
||||
|
@ -213,7 +213,7 @@ Add signed value to the token balance of the specified client and update its `me
|
|||
[968379616, 1968379616]
|
||||
```
|
||||
|
||||
## les_setClientParams
|
||||
## les_setClientParams {#les-setclientparams}
|
||||
|
||||
Set capacity and pricing factors for the specified list of connected clients or for all connected clients if the ID list is empty.
|
||||
|
||||
|
@ -238,7 +238,7 @@ Set capacity and pricing factors for the specified list of connected clients or
|
|||
null
|
||||
```
|
||||
|
||||
## les_setDefaultParams
|
||||
## les_setDefaultParams {#les-setdefaultparams}
|
||||
|
||||
Set default pricing factors for subsequently connected clients.
|
||||
|
||||
|
@ -262,7 +262,7 @@ Set default pricing factors for subsequently connected clients.
|
|||
null
|
||||
```
|
||||
|
||||
## les_latestCheckpoint
|
||||
## les_latestCheckpoint {#les-latestcheckpoint}
|
||||
|
||||
Get the index and hashes of the latest known checkpoint.
|
||||
|
||||
|
@ -279,7 +279,7 @@ Get the index and hashes of the latest known checkpoint.
|
|||
["0x110", "0x6eedf8142d06730b391bfcbd32e9bbc369ab0b46ae226287ed5b29505a376164", "0x191bb2265a69c30201a616ae0d65a4ceb5937c2f0c94b125ff55343d707463e5", "0xf58409088a5cb2425350a59d854d546d37b1e7bef8bbf6afee7fd15f943d626a"]
|
||||
```
|
||||
|
||||
## les_getCheckpoint
|
||||
## les_getCheckpoint {#les-getcheckpoint}
|
||||
|
||||
Get checkpoint hashes by index.
|
||||
|
||||
|
@ -296,7 +296,7 @@ Get checkpoint hashes by index.
|
|||
["0x93eb4af0b224b1097e09181c2e51536fe0a3bf3bb4d93e9a69cab9eb3e28c75f", "0x0eb055e384cf58bc72ca20ca5e2b37d8d4115dce80ab4a19b72b776502c4dd5b", "0xda6c02f7c51f9ecc3eca71331a7eaad724e5a0f4f906ce9251a2f59e3115dd6a"]
|
||||
```
|
||||
|
||||
## les_getCheckpointContractAddress
|
||||
## les_getCheckpointContractAddress {#les-getcheckpointcontractaddress}
|
||||
|
||||
Get the address of the checkpoint oracle contract.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Documentation for the JSON-RPC API "miner" namespace
|
|||
|
||||
The `miner` API is **now deprecated** because mining was switched off at the transition to proof-of-stake. It existed to provide remote control the node's mining operation and set various mining specific settings. It is provided here for historical interest!
|
||||
|
||||
## miner_getHashrate
|
||||
## miner_getHashrate {#miner-hashrate}
|
||||
|
||||
Get hashrate in H/s (Hash operations per second).
|
||||
|
||||
|
@ -14,7 +14,7 @@ Get hashrate in H/s (Hash operations per second).
|
|||
| Console | `miner.getHashrate()` |
|
||||
| RPC | `{"method": "miner_getHashrate", "params": []}` |
|
||||
|
||||
## miner_setExtra
|
||||
## miner_setExtra {#miner-setextra}
|
||||
|
||||
Sets the extra data a miner can include when miner blocks. This is capped at 32 bytes.
|
||||
|
||||
|
@ -24,7 +24,7 @@ Sets the extra data a miner can include when miner blocks. This is capped at 32
|
|||
| Console | `miner.setExtra(string)` |
|
||||
| RPC | `{"method": "miner_setExtra", "params": [string]}` |
|
||||
|
||||
## miner_setGasPrice
|
||||
## miner_setGasPrice {#miner-setgasprice}
|
||||
|
||||
Sets the minimal accepted gas price when mining transactions. Any transactions that are below this limit are excluded from the mining process.
|
||||
|
||||
|
@ -34,7 +34,7 @@ Sets the minimal accepted gas price when mining transactions. Any transactions t
|
|||
| Console | `miner.setGasPrice(number)` |
|
||||
| RPC | `{"method": "miner_setGasPrice", "params": [number]}` |
|
||||
|
||||
## miner_setRecommitInterval
|
||||
## miner_setRecommitInterval {#miner-setrecommitinterval}
|
||||
|
||||
Updates the interval for recomitting the miner sealing work.
|
||||
|
||||
|
@ -43,7 +43,7 @@ Updates the interval for recomitting the miner sealing work.
|
|||
| Console | `miner.setRecommitInterval(interval int)` |
|
||||
| RPC | `{"method": "miner_setRecommitInterval", "params": [number]}` |
|
||||
|
||||
## miner_start
|
||||
## miner_start {#miner-start}
|
||||
|
||||
Start the CPU mining process with the given number of threads and generate a new DAG if need be.
|
||||
|
||||
|
@ -53,7 +53,7 @@ Start the CPU mining process with the given number of threads and generate a new
|
|||
| Console | `miner.start(number)` |
|
||||
| RPC | `{"method": "miner_start", "params": [number]}` |
|
||||
|
||||
## miner_stop
|
||||
## miner_stop {#miner-stop}
|
||||
|
||||
Stop the CPU mining operation.
|
||||
|
||||
|
@ -63,7 +63,7 @@ Stop the CPU mining operation.
|
|||
| Console | `miner.stop()` |
|
||||
| RPC | `{"method": "miner_stop", "params": []}` |
|
||||
|
||||
## miner_setEtherbase
|
||||
## miner_setEtherbase {#miner-setetherbase}
|
||||
|
||||
Sets the etherbase, where mining rewards will go.
|
||||
|
||||
|
@ -73,7 +73,7 @@ Sets the etherbase, where mining rewards will go.
|
|||
| Console | `miner.setEtherbase(address)` |
|
||||
| RPC | `{"method": "miner_setEtherbase", "params": [address]}` |
|
||||
|
||||
## miner_setGasLimit
|
||||
## miner_setGasLimit {#miner-setgaslimit}
|
||||
|
||||
Sets the gas limit the miner will target when mining. Note: on networks where EIP-1559 is activated, this should be set to twice the gas target (i.e. the effective gas used on average per block) to be.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Documentation for the JSON-RPC API "net" namespace
|
|||
|
||||
The `net` API provides insight about the networking aspect of the client.
|
||||
|
||||
## net_listening
|
||||
## net_listening {#net-listening}
|
||||
|
||||
Returns an indication if the node is listening for network connections.
|
||||
|
||||
|
@ -14,7 +14,7 @@ Returns an indication if the node is listening for network connections.
|
|||
| Console | `net.listening` |
|
||||
| RPC | `{"method": "net_listening"}` |
|
||||
|
||||
## net_peerCount
|
||||
## net_peerCount {#net-peercount}
|
||||
|
||||
Returns the number of connected peers.
|
||||
|
||||
|
@ -23,7 +23,7 @@ Returns the number of connected peers.
|
|||
| Console | `net.peerCount` |
|
||||
| RPC | `{"method": "net_peerCount"}` |
|
||||
|
||||
## net_version
|
||||
## net_version {#net-version}
|
||||
|
||||
Returns the devp2p network ID (e.g. 1 for mainnet, 5 for goerli).
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@ title: personal Namespace
|
|||
description: Documentation for the JSON-RPC API "personal" namespace
|
||||
---
|
||||
|
||||
The personal API manages private keys in the key store.
|
||||
{% include note.html content="The personal namespace will be deprecated in the very near future." %}
|
||||
|
||||
## personal_deriveAccount
|
||||
The personal API managed private keys in the key store. It is deprecated in favour of using [Clef](/docs/tools/clef/Introduction.md) for interacting with accounts Please refer to the [ns_personal deprecation page](/docs/interacting-with-geth/rpc/ns_personal_deprecation.md) to see the equivalent methods. The following documentation should be treated as archive information and users should migrate tousing Clef for account interactions.
|
||||
|
||||
## personal_deriveAccount {#personal-deriveaccount}
|
||||
|
||||
Requests a HD wallet to derive a new account, optionally pinning it for later reuse.
|
||||
|
||||
|
@ -14,7 +16,7 @@ Requests a HD wallet to derive a new account, optionally pinning it for later re
|
|||
| Console | `personal.deriveAccount(url, path, pin)` |
|
||||
| RPC | `{"method": "personal_deriveAccount", "params": [string, string, bool]}` |
|
||||
|
||||
## personal_importRawKey
|
||||
## personal_importRawKey {#personal-importrawkey}
|
||||
|
||||
Imports the given unencrypted private key (hex string) into the key store, encrypting it with the passphrase.
|
||||
|
||||
|
@ -25,7 +27,7 @@ Returns the address of the new account.
|
|||
| Console | `personal.importRawKey(keydata, passphrase)` |
|
||||
| RPC | `{"method": "personal_importRawKey", "params": [string, string]}` |
|
||||
|
||||
## personal_initializeWallets
|
||||
## personal_initializeWallets {#personal-intializewallets}
|
||||
|
||||
Initializes a new wallet at the provided URL by generating and returning a new private key.
|
||||
|
||||
|
@ -34,7 +36,7 @@ Initializes a new wallet at the provided URL by generating and returning a new p
|
|||
| Console | `personal.initializeWallet(url)` |
|
||||
| RPC | `{"method": "personal_initializeWallet", "params": [string]}` |
|
||||
|
||||
## personal_listAccounts
|
||||
## personal_listAccounts {#personal-listaccounts}
|
||||
|
||||
Returns all the Ethereum account addresses of all keys in the key store.
|
||||
|
||||
|
@ -50,7 +52,7 @@ Returns all the Ethereum account addresses of all keys in the key store.
|
|||
["0x5e97870f263700f46aa00d967821199b9bc5a120", "0x3d80b31a78c30fc628f20b2c89d7ddbf6e53cedc"]
|
||||
```
|
||||
|
||||
## personal_listWallets
|
||||
## personal_listWallets {#personal-listwallets}
|
||||
|
||||
Returns a list of wallets this node manages.
|
||||
|
||||
|
@ -73,7 +75,7 @@ Returns a list of wallets this node manages.
|
|||
}]
|
||||
```
|
||||
|
||||
## personal_lockAccount
|
||||
## personal_lockAccount {#personal-lockaccount}
|
||||
|
||||
Removes the private key with given address from memory. The account can no longer be used to send transactions.
|
||||
|
||||
|
@ -82,7 +84,7 @@ Removes the private key with given address from memory. The account can no longe
|
|||
| Console | `personal.lockAccount(address)` |
|
||||
| RPC | `{"method": "personal_lockAccount", "params": [string]}` |
|
||||
|
||||
## personal_newAccount
|
||||
## personal_newAccount {#personal-newaccount}
|
||||
|
||||
Generates a new private key and stores it in the key store directory. The key file is encrypted with the given passphrase.
|
||||
Returns the address of the new account. At the geth console, `newAccount` will prompt for a passphrase when it is not supplied as the argument.
|
||||
|
@ -108,7 +110,7 @@ The passphrase can also be supplied as a string.
|
|||
"0x3d80b31a78c30fc628f20b2c89d7ddbf6e53cedc"
|
||||
```
|
||||
|
||||
## personal_openWallet
|
||||
## personal_openWallet {#personal-openwallet}
|
||||
|
||||
Initiates a hardware wallet opening procedure by establishing a USB connection and then attempting to authenticate via the provided passphrase. Note,
|
||||
the method may return an extra challenge requiring a second open (e.g. the Trezor PIN matrix challenge).
|
||||
|
@ -118,7 +120,7 @@ the method may return an extra challenge requiring a second open (e.g. the Trezo
|
|||
| Console | `personal.openWallet(url, passphrase)` |
|
||||
| RPC | `{"method": "personal_openWallet", "params": [string, string]}` |
|
||||
|
||||
## personal_unlockAccount
|
||||
## personal_unlockAccount {#personal-unlockaccount}
|
||||
|
||||
Decrypts the key with the given address from the key store.
|
||||
|
||||
|
@ -157,7 +159,7 @@ Passphrase:
|
|||
true
|
||||
```
|
||||
|
||||
## personal_unpair
|
||||
## personal_unpair {#personal-unpair}
|
||||
|
||||
Deletes a pairing between wallet and Geth.
|
||||
|
||||
|
@ -166,7 +168,7 @@ Deletes a pairing between wallet and Geth.
|
|||
| Console | `personal.unpair(url, pin)` |
|
||||
| RPC | `{"method": "personal_unpair", "params": [string, string]}` |
|
||||
|
||||
## personal_sendTransaction
|
||||
## personal_sendTransaction {#personal-sendtransaction}
|
||||
|
||||
Validate the given passphrase and submit transaction.
|
||||
|
||||
|
@ -186,7 +188,7 @@ undefined
|
|||
0x8474441674cdd47b35b875fd1a530b800b51a5264b9975fb21129eeb8c18582f
|
||||
```
|
||||
|
||||
## personal_sign
|
||||
## personal_sign {#personal-sign}
|
||||
|
||||
The sign method calculates an Ethereum specific signature with:
|
||||
`sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))`.
|
||||
|
@ -207,7 +209,7 @@ See ecRecover to verify the signature.
|
|||
"0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"
|
||||
```
|
||||
|
||||
## personal_signTransaction
|
||||
## personal_signTransaction {#personal-signtransaction}
|
||||
|
||||
SignTransaction will create a transaction from the given arguments and tries to sign it with the key associated with `tx.from`. If the given passwd isn't able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast to other nodes. The first argument is a [transaction object](/docs/interacting_with_geth/RPC/objects) and the second argument is the password, similar to `personal_sendTransaction`.
|
||||
|
||||
|
@ -216,7 +218,7 @@ SignTransaction will create a transaction from the given arguments and tries to
|
|||
| Console | `personal.signTransaction(tx, passphrase)` |
|
||||
| RPC | `{"method": "personal_signTransaction", "params": [tx, string]}` |
|
||||
|
||||
## personal_ecRecover
|
||||
## personal_ecRecover {#personal-ecrecover}
|
||||
|
||||
`ecRecover` returns the address associated with the private key that was used to calculate the signature in `personal_sign`.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Documentation for the JSON-RPC API "txpool" namespace
|
|||
|
||||
The `txpool` API gives access to several non-standard RPC methods to inspect the contents of the transaction pool containing all the currently pending transactions as well as the ones queued for future processing.
|
||||
|
||||
## txpool_content
|
||||
## txpool_content {#txpool-content}
|
||||
|
||||
The `content` inspection property can be queried to list the exact details of all the transactions currently pending for inclusion in the next block(s), as well as the ones that are being scheduled for future execution only.
|
||||
|
||||
|
@ -104,7 +104,7 @@ Please note, there may be multiple transactions associated with the same account
|
|||
}
|
||||
```
|
||||
|
||||
## txpool_contentFrom
|
||||
## txpool_contentFrom {#txpool-contentfrom}
|
||||
|
||||
Retrieves the transactions contained within the txpool, returning pending as well as queued transactions of this address, grouped by nonce.
|
||||
|
||||
|
@ -113,7 +113,7 @@ Retrieves the transactions contained within the txpool, returning pending as wel
|
|||
| Console | `txpool.contentFrom(address)` |
|
||||
| RPC | `{"method": "txpool_contentFrom, "params": [string]"}` |
|
||||
|
||||
## txpool_inspect
|
||||
## txpool_inspect {#txpool-inspect}
|
||||
|
||||
The `inspect` inspection property can be queried to list a textual summary of all the transactions currently pending for inclusion in the next block(s), as well as the ones that are being scheduled for future execution only. This is a method specifically tailored to developers to quickly see the transactions in the pool and find any potential issues.
|
||||
|
||||
|
@ -182,7 +182,7 @@ Please note, there may be multiple transactions associated with the same account
|
|||
}
|
||||
```
|
||||
|
||||
## txpool_status
|
||||
## txpool_status {#txpool-status}
|
||||
|
||||
The `status` inspection property can be queried for the number of transactions currently pending for inclusion in the next block(s), as well as the ones that are being scheduled for future execution only.
|
||||
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
---
|
||||
title: Personal namespace deprecation notes
|
||||
description: Alternatives to the methods in the deprecated personal namespace
|
||||
---
|
||||
|
||||
The JSON-RPC API's `personal` namespace has historically been used to manage accounts and sign transactions and data over RPC. However, it is being deprecated in favour of using [Clef](/docs/tools/clef/Introduction.md) as an external signer and account manager. One of the major changes is moving away from indiscriminate locking and unlocking of accounts and instead using Clef to explicitly approve or deny specific actions. This page shows the suggested replacement for each method in `personal`.
|
||||
|
||||
## Methods without replacements
|
||||
|
||||
### personal_unlockAccount
|
||||
|
||||
There is no need for a direct replacement for `personal_unlockAccount`. Using Clef to manually approve actions or to attest custom rulesets is a much more secure way to interact with accounts without needing to indiscriminately unlock accounts.
|
||||
|
||||
### personal_lockAccount
|
||||
|
||||
There is no need for a direct replacement for `personal_lockAccount` because account locking/unlocking is replaced by Clef's approve/deny logic. This is a more secure way to interact with accounts.
|
||||
|
||||
### personal.unpair
|
||||
|
||||
Unpair deletes a pairing between some specific types of smartcard wallet and Geth. There is not yet an equivalent method in Clef.
|
||||
|
||||
### personal_initializeWallet
|
||||
|
||||
InitializeWallet is for initializing some specific types of smartcard wallet at a provided URL. There is not yet a corresponding method in Clef.
|
||||
|
||||
## Methods with replacements:
|
||||
|
||||
### personal_listAccounts
|
||||
|
||||
`personal_listAccounts` displays the addresses of all accounts in the keystore. It is identical to `eth.accounts`. Calling `eth.accounts` requires manual approval in Clef (unless a rule for it has been attested). There is also Clef's `list-accounts` command that can be called from the terminal.
|
||||
|
||||
Examples:
|
||||
|
||||
```sh
|
||||
# eth_accounts using curl
|
||||
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}'
|
||||
```
|
||||
|
||||
```js
|
||||
// eth_accounts in Geth's JS console
|
||||
eth.accounts;
|
||||
```
|
||||
|
||||
```sh
|
||||
# clef list-accounts in the terminal
|
||||
clef list-accounts
|
||||
```
|
||||
|
||||
### personal_deriveAccount
|
||||
|
||||
`personal_deriveAccount` requests a hardware wallet to derive a new account, optionally pinning it for later use. This method is identical to `clef_deriveAccount`. The Clef method is not externally exposed so it must be called via a UI.
|
||||
|
||||
### personal.ecRecover
|
||||
|
||||
`personal_ecRecover` returns the address for the account that was used to create a signature. An equivalent method, `account_ecRecover` is available on the Clef external API.
|
||||
|
||||
Example call:
|
||||
|
||||
```sh
|
||||
curl --data '{"id": 4, "jsonrpc": "2.0", "method": "account_ecRecover","params": ["0xaabbccdd", "0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c"]}' -X POST localhost:8550
|
||||
```
|
||||
|
||||
### personal_importRawKey
|
||||
|
||||
`personal.importRawKey` was used to create a new account in the keystore from a raw private key. Clef has an equivalent method that can be invoked in the terminal using:
|
||||
|
||||
```sh
|
||||
clef importraw <private-key-as-hex-string>
|
||||
```
|
||||
|
||||
### personal_listWallets
|
||||
|
||||
As opposed to `listAccounts`, this method lists full details, including usb path or keystore-file paths. The equivalent method is `clef_listWallets`. This method can be called from the terminal using:
|
||||
|
||||
```sh
|
||||
clef list-wallets
|
||||
```
|
||||
|
||||
### personal_newAccount
|
||||
|
||||
`personal_newAccount` was used to create a new accoutn and save it in the keystore. Clef has an equivalent method, `account_new`. It can be accessed on the terminal using an http request or using a Clef command:
|
||||
|
||||
Example call (curl):
|
||||
|
||||
```sh
|
||||
curl --data '{"id": 1, "jsonrpc": "2.0", "method": "account_new", "params": []}' -X POST localhost:8550
|
||||
```
|
||||
|
||||
Example call (Clef command):
|
||||
|
||||
```sh
|
||||
clef newaccount
|
||||
```
|
||||
|
||||
Both require manual approval in Clef unless a custom ruleset is in place.
|
||||
|
||||
### personal_openWallet
|
||||
|
||||
`personal_OpenWallet` initiates a hardware wallet opening procedure by establishing a USB connection and then attempting to authenticate via the provided passphrase. Note, the method may return an extra challenge requiring a second open (e.g. the Trezor PIN matrix challenge). `personal_openWallet` is identical to `clef_openWallet`. The Clef method is not externally eposed, meaning it must be called via a UI.
|
||||
|
||||
### personal_sendTransaction
|
||||
|
||||
`personal_sendTransaction` ws used to sign and submit a transaction. This can be done using `eth_sendTransaction`, requiring manual approval in Clef.
|
||||
|
||||
Example call (Javascript console):
|
||||
|
||||
```js
|
||||
// this command requires 2x approval in Clef because it loads account data via eth.accounts[0]
|
||||
// and eth.accounts[1]
|
||||
var tx = { from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(0.1, 'ether') };
|
||||
|
||||
// then send the transaction
|
||||
eth.sendTransaction(tx);
|
||||
```
|
||||
|
||||
Example call (terminal)
|
||||
|
||||
```sh
|
||||
curl --data '{"id":1,"jsonrpc":"2.0", "method":"eth_sendTransaction","params":[{"from": "0xE70CAD05D0D54Ae3C9Fe5442f901E0433f9bd14B", "to":"0x4FDc03d09Ffca5Bba3138149E29D85C8A9E2Ac42", "gas":"21000","gasPrice":"20000000000", "nonce":"94"}]}' -H "Content-Type: application/json" -X POST localhost:8545
|
||||
```
|
||||
|
||||
### personal_sign
|
||||
|
||||
The sign method calculates an Ethereum specific signature with `sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))`. Adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.
|
||||
|
||||
`personal.sign` is equivalent to Clef's `account_signData`. It returns the calculated signature.
|
||||
|
||||
Example call:
|
||||
|
||||
```sh
|
||||
curl --data {"id": 3, "jsonrpc": "2.0", "method": "account_signData", "params": ["data/plain", "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db","0xaabbccdd"]} -X POST localhost:8550
|
||||
```
|
||||
|
||||
Clef also has `account_signTypedData` that signs data structured according to [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) and returns the signature.
|
||||
|
||||
Example call (use the following as a template for `<data>` in `curl --data <data> -X POST localhost:8550 -H "Content-Type: application/json"`)
|
||||
|
||||
```sh
|
||||
{
|
||||
"id": 68,
|
||||
"jsonrpc": "2.0",
|
||||
"method": "account_signTypedData",
|
||||
"params": [
|
||||
"0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826",
|
||||
{
|
||||
"types": {
|
||||
"EIP712Domain": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "version",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "chainId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "verifyingContract",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"Person": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "wallet",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"Mail": [
|
||||
{
|
||||
"name": "from",
|
||||
"type": "Person"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "Person"
|
||||
},
|
||||
{
|
||||
"name": "contents",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"primaryType": "Mail",
|
||||
"domain": {
|
||||
"name": "Ether Mail",
|
||||
"version": "1",
|
||||
"chainId": 1,
|
||||
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
|
||||
},
|
||||
"message": {
|
||||
"from": {
|
||||
"name": "Cow",
|
||||
"wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
|
||||
},
|
||||
"to": {
|
||||
"name": "Bob",
|
||||
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
|
||||
},
|
||||
"contents": "Hello, Bob!"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### personal_signTransaction
|
||||
|
||||
`personal_signTransaction` was used to create and sign a transaction from the given arguments. The transaction was returned in RLP-form, not broadcast to other nodes. The equivalent method is Clef's `account_signTransaction` from the external API. The arguments are a transaction object (`{"from": , "to": , "gas": , "maxPriorityFeePerGas": , "MaxFeePerGas": , "value": , "data": , "nonce": }`)) and an optional method signature that enables Clef to decode the calldata and show the user the methods, arguments and values being sent.
|
||||
|
||||
Example call (terminal):
|
||||
|
||||
```sh
|
||||
curl --data '{"id": 2, "jsonrpc": "2.0", "method": "account_signTransaction", "params": [{"from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", "gas": "0x55555","gasPrice": "0x1234", "input": "0xabcd", "nonce": "0x0", "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value": "0x1234"}]}' -X POST -H "Content-Type: application/json" localhost:8550
|
||||
```
|
|
@ -5,7 +5,7 @@ description: Data structures used for RPC methods
|
|||
|
||||
The following are data structures which are used for various RPC methods.
|
||||
|
||||
## Transaction call object
|
||||
## Transaction call object {#transaction-call-object}
|
||||
|
||||
The _transaction call object_ contains all the necessary parameters for executing an EVM contract method.
|
||||
|
||||
|
|
|
@ -31,14 +31,14 @@ to cancel the subscription:
|
|||
{"jsonrpc":"2.0","id":1,"result":true}
|
||||
```
|
||||
|
||||
## Considerations
|
||||
## Considerations {#considerations}
|
||||
|
||||
1. Notifications are sent for current events and not for past events. For use cases that depend on not to miss any notifications subscriptions are probably not the best option.
|
||||
2. Subscriptions require a full duplex connection. Geth offers such connections in the form of WebSocket and IPC (enabled by default).
|
||||
3. Subscriptions are coupled to a connection. If the connection is closed all subscriptions that are created over this connection are removed.
|
||||
4. Notifications are stored in an internal buffer and sent from this buffer to the client. If the client is unable to keep up and the number of buffered notifications reaches a limit (currently 10k) the connection is closed. Keep in mind that subscribing to some events can cause a flood of notifications, e.g. listening for all logs/blocks when the node starts to synchronize.
|
||||
|
||||
## Create subscription
|
||||
## Create subscription {#create-subscriptions}
|
||||
|
||||
Subscriptions are created with a regular RPC call with `eth_subscribe` as method and the subscription name as first parameter. If successful it returns the subscription id.
|
||||
|
||||
|
@ -54,7 +54,7 @@ Subscriptions are created with a regular RPC call with `eth_subscribe` as method
|
|||
{"id": 1, "jsonrpc": "2.0", "result": "0x9cef478923ff08bf67fde6c64013158d"}
|
||||
```
|
||||
|
||||
## Cancel subscription
|
||||
## Cancel subscription {#cancel-subscriptions}
|
||||
|
||||
Subscriptions are cancelled with a regular RPC call with `eth_unsubscribe` as method and the subscription id as first parameter. It returns a bool indicating if the subscription was cancelled successful.
|
||||
|
||||
|
@ -69,9 +69,9 @@ Subscriptions are cancelled with a regular RPC call with `eth_unsubscribe` as me
|
|||
{"jsonrpc":"2.0","id":1,"result":true}
|
||||
```
|
||||
|
||||
## Supported Subscriptions
|
||||
## Supported Subscriptions {#supported-subscriptions}
|
||||
|
||||
### newHeads
|
||||
### newHeads {#newheads}
|
||||
|
||||
Fires a notification each time a new header is appended to the chain, including chain reorganizations. Users can use the bloom filter to determine if the block contains logs that are interested to them. Note that if geth receives multiple blocks simultaneously, e.g. catching up after being out of sync, only the last block is emitted.
|
||||
|
||||
|
@ -113,7 +113,7 @@ returns
|
|||
}
|
||||
```
|
||||
|
||||
### logs
|
||||
### logs {#logs}
|
||||
|
||||
Returns logs that are included in new imported blocks and match the given filter criteria.
|
||||
|
||||
|
@ -139,7 +139,7 @@ returns
|
|||
{"jsonrpc":"2.0","method":"eth_subscription","params": {"subscription":"0x4a8a4c0517381924f9838102c5a4dcb7","result":{"address":"0x8320fe7702b96808f7bbc0d4a888ed1468216cfd","blockHash":"0x61cdb2a09ab99abf791d474f20c2ea89bf8de2923a2d42bb49944c8c993cbf04","blockNumber":"0x29e87","data":"0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003","logIndex":"0x0","topics":["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"],"transactionHash":"0xe044554a0a55067caafd07f8020ab9f2af60bdfe337e395ecd84b4877a3d1ab4","transactionIndex":"0x0"}}}
|
||||
```
|
||||
|
||||
### newPendingTransactions
|
||||
### newPendingTransactions {#newpendingtransactions}
|
||||
|
||||
Returns the hash for all transactions that are added to the pending state and are signed with a key that is available in the node.
|
||||
|
||||
|
@ -169,7 +169,7 @@ returns
|
|||
}
|
||||
```
|
||||
|
||||
### syncing
|
||||
### syncing {#syncing}
|
||||
|
||||
Indicates when the node starts or stops synchronizing. The result can either be a boolean indicating that the synchronization has started (true), finished (false) or an object with various progress indicators.
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ InfluxDB is running and configured to store metrics from Geth.
|
|||
|
||||
## Preparing Geth {#preparing-geth}
|
||||
|
||||
After setting up database, metrics need to be enabled in Geth. Various options are available, as documented in the `METRICS AND STATS OPTIONS`
|
||||
After setting up database, metrics need to be enabled in Geth. Various options are available, as documented in the `METRICS AND STATS OPTIONS`
|
||||
in `geth --help` and in our [metrics page](/docs/monitoring/metrics). In this case Geth will be configured to push data into InfluxDB. Basic setup specifies the endpoint where InfluxDB is reachable and authenticates the database.
|
||||
|
||||
```sh
|
||||
|
@ -132,16 +132,15 @@ For a Geth monitoring dashboard, copy the URL of [this dashboard](https://grafan
|
|||
|
||||
![Grafana 1](/public/images/docs/grafana.png)
|
||||
|
||||
## Customization {#customization}
|
||||
|
||||
## Customization
|
||||
|
||||
The dashboards can be customized further. Each panel can be edited, moved, removed or added. To learn more about how dashboards work, refer to
|
||||
The dashboards can be customized further. Each panel can be edited, moved, removed or added. To learn more about how dashboards work, refer to
|
||||
[Grafana's documentation](https://grafana.com/docs/grafana/latest/dashboards/).
|
||||
|
||||
Some users might also be interested in automatic [alerting](https://grafana.com/docs/grafana/latest/alerting/), which sets up alert notifications that are sent automatically when metrics reach certain values. Various communication channels are supported.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page has outlined how to set up a simple node monitoring dashboard using Grafana.
|
||||
|
||||
***NB: this page was adapted from a tutorial on ethereum.org written by Mario Havel***
|
||||
**_NB: this page was adapted from a tutorial on ethereum.org written by Mario Havel_**
|
||||
|
|
|
@ -14,7 +14,7 @@ This can be configured using the public Ethstats server for Ethereum mainnet or
|
|||
public testnets, or using a local copy of Ethstats for private networks. This page will
|
||||
demonstrate how to set up an Ethstats dashboard for private and public networks.
|
||||
|
||||
## Prerequisites
|
||||
## Prerequisites {#prerequisites}
|
||||
|
||||
To follow the instructions on this page the following are required:
|
||||
|
||||
|
@ -23,7 +23,7 @@ To follow the instructions on this page the following are required:
|
|||
- NPM
|
||||
- Git
|
||||
|
||||
## Ethstats
|
||||
## Ethstats {#ethstats}
|
||||
|
||||
Ethstats has three components:
|
||||
|
||||
|
@ -40,7 +40,7 @@ Note that the Ethstats dashboard is not a reliable source of information about t
|
|||
network because submitting data to the Ethstats server is voluntary and has to be configured by
|
||||
individual nodes. Therefore, many nodes are omitted from the summary statistics.
|
||||
|
||||
## How to use
|
||||
## How to use {#how-to-use}
|
||||
|
||||
To report statistics about the local node to Ethstats, an Ethstats server and Ethstats client both have
|
||||
to be installed alongside Geth. There are several options for installing Ethstats clients and servers,
|
||||
|
@ -64,7 +64,7 @@ geth <other commands> --ethstats node1:secret:127.0.0.1:9000
|
|||
The local node will then report to Ethstats, and the statistics will be displayed in a dashboard that can be
|
||||
accessed via the web browser.
|
||||
|
||||
## Note on WS_secret
|
||||
## Note on WS_secret {#note-on-ws-secret}
|
||||
|
||||
The `WS_secret` parameter is required for connecting to an Ethstats server. For a local network this can be user-defined
|
||||
on startup by providing it as an environment variable. However, for Ethereum mainnet and the public testnets predefined
|
||||
|
|
|
@ -7,11 +7,11 @@ Geth includes a variety of optional metrics that can be reported to the user. Ho
|
|||
|
||||
The goal of the Geth metrics system is that - similar to logs - arbitrary metric collections can be added to any part of the code without requiring fancy constructs to analyze them (counter variables, public interfaces, crossing over the APIs, console hooks, etc). Instead, metrics should be "updated" whenever and wherever needed and be automatically collected, surfaced through the APIs, queryable and visualizable for analysis.
|
||||
|
||||
## Metric types
|
||||
## Metric types {#metric-types}
|
||||
|
||||
Geth's metrics can be classified into four types: meters, timers, counters and guages.
|
||||
|
||||
### Meters
|
||||
### Meters {#meters}
|
||||
|
||||
Analogous to physical meters (electricity, water, etc), Geth's meters are capable of measuring the _amount_ of "things" that pass through and at the _rate_ at which they do. A meter doesn't have a specific unit of measure (byte, block, malloc, etc), it just counts arbitrary _events_. At any point in time a meter can report:
|
||||
|
||||
|
@ -20,7 +20,7 @@ Analogous to physical meters (electricity, water, etc), Geth's meters are capabl
|
|||
- _Weighted throughput rate_ in the last _1_, _5_ and _15_ minutes (events / second)
|
||||
("weighted" means that recent seconds count more that in older ones\*)
|
||||
|
||||
### Timers
|
||||
### Timers {#timers}
|
||||
|
||||
Timers are extensions of _meters_, the _duration_ of an event is collected alongside a log of its occurrence. Similarly to meters, a timer can also measure arbitrary events but each requires a duration to be assigned individually. In addition generating all of the meter report types, a timer also reports:
|
||||
|
||||
|
@ -30,15 +30,15 @@ Timers are extensions of _meters_, the _duration_ of an event is collected along
|
|||
- Percentile 80: general performance (these should be optimised)
|
||||
- Percentile 95: worst case outliers (rare, just handle gracefully)
|
||||
|
||||
### Counters:
|
||||
### Counters: {#counters}
|
||||
|
||||
A counter is a single int64 value that can be incremented and decremented. The current value of the counter can be queried.
|
||||
|
||||
### Gauges:
|
||||
### Gauges: {#guages}
|
||||
|
||||
A gauge is a single int64 value. Its value can increment and decrement - as with a counter - but can also be set arbitrarily.
|
||||
|
||||
## Querying metrics
|
||||
## Querying metrics {#querying-metrics}
|
||||
|
||||
Geth collects metrics if the `--metrics` flag is provided at startup. Those metrics are available via an HTTP server if the `--metrics.addr` flag is also provided. By default the metrics are served at `127.0.0.1:6060/debug/metrics` but a custom IP address can be provided. A custom port can also be provided to the `--metrics.port` flag. More computationally expensive metrics are toggled on or off by providing or omitting the `--metrics.expensive` flag. For example, to serve all metrics at the default address and port:
|
||||
|
||||
|
@ -79,7 +79,7 @@ Geth also supports dumping metrics directly into an influx database. In order to
|
|||
--metrics.influxdb.organization value InfluxDB organization name (v2 only) (default: "geth")
|
||||
```
|
||||
|
||||
## Creating and updating metrics
|
||||
## Creating and updating metrics {#creating-and-updating-metrics}
|
||||
|
||||
Metrics can be added easily in the Geth source code:
|
||||
|
||||
|
@ -107,6 +107,6 @@ timer.UpdateSince(time) // Record an event that started at `time`
|
|||
timer.Time(function) // Measure and record the execution of `function`
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Geth can be configured to report metrics to an HTTP server or database. These functions are disabled by default but can be configured by passing the appropriate commands on startup. Users can easily create custom metrics by adding them to the Geth source code, following the instructions on this page.
|
||||
|
|
|
@ -5,13 +5,13 @@ description: Read, watch and listen more about Geth and Ethereum
|
|||
|
||||
Here are more resources for a deeper understanding of Geth and related topics.
|
||||
|
||||
## Read
|
||||
## Read {#read}
|
||||
|
||||
[Geth team AMA: August 2022](https://www.reddit.com/r/cryptoall/comments/wpr6dk/ama_we_are_the_go_ethereum_geth_team_18_august/)
|
||||
|
||||
[Ethereum stack exchange](https://ethereum.stackexchange.com/)
|
||||
|
||||
## Watch
|
||||
## Watch {#watch}
|
||||
|
||||
[Geth team AMA at Devcon 6, Bogota](https://youtu.be/Wr_SHOmz4lc?t=10714)
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@ $ cd $GOPATH/src/github.com/ethereum/go-ethereum
|
|||
$ go build ./cmd/abigen
|
||||
```
|
||||
|
||||
## What is an ABI?
|
||||
## What is an ABI? {#what-is-an-abi}
|
||||
|
||||
Ethereum smart contracts have a schema that defines its functions and return types in the form of a JSON file. This JSON file is known as an _Application Binary Interface_, or ABI. The ABI acts as a specification for precisely how to encode data sent to a contract and how to decode the data the contract sends back. The ABI is the only essential piece of information required to generate Go bindings. Go developers can then use the bindings to interact with the contract from their Go application without having to deal directly with data encoding and decoding. An ABI is generated when a contract is compiled.
|
||||
|
||||
### Generating the bindings
|
||||
### Generating the bindings {#generating-bindings}
|
||||
|
||||
To demonstrate the binding generator a contract is required. The contract `Storage.sol` implements two very simple functions: `store` updates a user-defined `uint256` to the contract's storage, and `retrieve` displays the value stored in the contract to the user. The Solidity code is as follows:
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ title: Introduction to Clef
|
|||
description: Introduction to the external signing tool, Clef
|
||||
---
|
||||
|
||||
## What is Clef?
|
||||
## What is Clef? {#what-is-clef}
|
||||
|
||||
Clef is a tool for **signing transactions and data** in a secure local environment. It is intended to become a more composable and secure replacement for Geth's built-in account management. Clef decouples key management from Geth itself, meaning it can be used as an independent, standalone key management and signing application, or it can be integrated into Geth. This provides a more flexible modular tool compared to Geth's account manager. Clef can be used safely in situations where access to Ethereum is via a remote and/or untrusted node because signing happens locally, either manually or automatically using custom rulesets. The separation of Clef from the node itself enables it to run as a daemon on the same machine as the client software, on a secure usb-stick like [USB armory](https://inversepath.com/usbarmory), or even a separate VM in a [QubesOS](https://www.qubes-os.org/) type setup.
|
||||
|
||||
## Installing and starting Clef
|
||||
## Installing and starting Clef {#installing-and-starting-clef}
|
||||
|
||||
Clef comes bundled with Geth and can be built along with Geth and the other bundled tools using:
|
||||
|
||||
|
@ -54,7 +54,7 @@ You should treat 'masterseed.json' with utmost secrecy and make a backup of it!
|
|||
* The master seed does not contain your accounts, those need to be backed up separately!
|
||||
```
|
||||
|
||||
## Security model
|
||||
## Security model {#security-model}
|
||||
|
||||
One of the major benefits of Clef is that it is decoupled from the client software, meaning it can be used by users and dapps to sign data and transactions in a secure, local environment and send the signed packet to an arbitrary Ethereum entry-point, which might include, for example, an untrusted remote node. Alternatively, Clef can simply be used as a standalone, composable signer that can be a backend component for decentralized applications. This requires a secure architecture that separates cryptographic operations from user interactions and internal/external communication.
|
||||
|
||||
|
@ -78,7 +78,7 @@ In the case illustrated in the schematic above, Geth would be started with `--si
|
|||
|
||||
Most users use Clef by manually approving transactions through the UI as in the schematic above, but it is also possible to configure Clef to sign transactions without always prompting the user. This requires defining the precise conditions under which a transaction will be signed. These conditions are known as `Rules` and they are small Javascript snippets that are _attested_ by the user by injecting the snippet's hash into Clef's secure whitelist. Clef is then started with the rule file, so that requests that satisfy the conditions in the whitelisted rule files are automatically signed. This is covered in detail on the [Rules page](/docs/tools/Clef/rules).
|
||||
|
||||
## Basic usage
|
||||
## Basic usage {#basic-usage}
|
||||
|
||||
Clef is started on the command line using the `clef` command. Clef can be configured by providing flags and commands to `clef` on startup. The full list of command line options is available [below](#command-line-options). Frequently used options include `--keystore` and `--chainid` which configure the path to an existing keystore and a network to connect to. These options default to `$HOME/.ethereum/keystore` and `1` (corresponding to Ethereum Mainnet) respectively. The following code snippet starts Clef, providing a custom path to an existing keystore and connecting to the Goerli testnet:
|
||||
|
||||
|
@ -109,7 +109,7 @@ Requests requiring account access or signing now require explicit consent in thi
|
|||
|
||||
A much more detailed Clef tutorial is available on the [Tutorial page](/docs/tools/Clef/tutorial).
|
||||
|
||||
## Command line options
|
||||
## Command line options {#command-line-options}
|
||||
|
||||
```sh
|
||||
COMMANDS:
|
||||
|
@ -145,6 +145,6 @@ GLOBAL OPTIONS:
|
|||
--suppress-bootwarn If set, does not show the warning during boot
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Clef is an external key management and signer tool that comes bundled with Geth but can either be used as a backend account manager and signer for Geth or as a completely separate standalone application. Being modular and composable it can be used as a component in decentralized applications or to sign data and transactions in untrusted environments. Clef is intended to eventually replace Geth's built-in account management tools.
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Reference documentation for the Clef APIs
|
|||
|
||||
Clef uses two separate APIs. The **external API** is an untrusted set of JSON-RPC methods that can be called by a user. The **internal API** is a set of JSON-RPC methods that can be called by a UI. The UI could be Clef's native command line interface or a custom UI.
|
||||
|
||||
## External API
|
||||
## External API {#external-api}
|
||||
|
||||
Clef listens to HTTP requests on `http.addr`:`http.port` (or to IPC on `ipcpath`), with the same JSON-RPC standard as Geth. The messages are expected to be [JSON-RPC 2.0 standard](https://www.jsonrpc.org/specification).
|
||||
|
||||
|
@ -23,9 +23,9 @@ The External API encoding is as follows:
|
|||
|
||||
All hex encoded values must be prefixed with `0x`.
|
||||
|
||||
### Methods
|
||||
### Methods {#methods}
|
||||
|
||||
#### account_new
|
||||
#### account_new {#accountnew}
|
||||
|
||||
##### Create new password protected account
|
||||
|
||||
|
@ -60,7 +60,7 @@ Response
|
|||
}
|
||||
```
|
||||
|
||||
#### account_list
|
||||
#### account_list {#account-list}
|
||||
|
||||
##### List available accounts
|
||||
|
||||
|
@ -98,7 +98,7 @@ Response
|
|||
}
|
||||
```
|
||||
|
||||
#### account_signTransaction
|
||||
#### account_signTransaction {#account-signtransaction}
|
||||
|
||||
##### Sign transactions
|
||||
|
||||
|
@ -281,7 +281,7 @@ Bash example:
|
|||
{"jsonrpc":"2.0","id":67,"result":{"raw":"0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","tx":{"nonce":"0x0","gasPrice":"0x1","gas":"0x333","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0","value":"0x0","input":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012","v":"0x26","r":"0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e","s":"0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","hash":"0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"}}}
|
||||
```
|
||||
|
||||
#### account_signData
|
||||
#### account_signData {#account-signdata}
|
||||
|
||||
##### Sign data
|
||||
|
||||
|
@ -321,7 +321,7 @@ Response
|
|||
}
|
||||
```
|
||||
|
||||
#### account_signTypedData
|
||||
#### account_signTypedData {#account-signtypeddata}
|
||||
|
||||
##### Sign data
|
||||
|
||||
|
@ -423,7 +423,7 @@ Response
|
|||
}
|
||||
```
|
||||
|
||||
#### account_ecRecover
|
||||
#### account_ecRecover {#account-ecrecover}
|
||||
|
||||
##### Recover the signing address
|
||||
|
||||
|
@ -462,7 +462,7 @@ Response
|
|||
}
|
||||
```
|
||||
|
||||
#### account_version
|
||||
#### account_version {#accountversion}
|
||||
|
||||
##### Get external API version
|
||||
|
||||
|
@ -497,7 +497,7 @@ Response
|
|||
}
|
||||
```
|
||||
|
||||
## Internal (UI) API
|
||||
## Internal (UI) API {#internalapi}
|
||||
|
||||
Clef has one native console-based UI, for operation without any standalone tools. However, there is also an API to communicate with an external UI. To enable that UI, the signer needs to be started with the `--stdio-ui` option, which allocates `stdin` / `stdout` for the UI API.
|
||||
|
||||
|
@ -523,9 +523,9 @@ See the [ui API changelog](https://github.com/ethereum/go-ethereum/blob/master/c
|
|||
Whereas the `json` specification allows for linebreaks, linebreaks **should not** be used in this communication channel, to make
|
||||
things simpler for both parties.
|
||||
|
||||
### Methods
|
||||
### Methods {#methods}
|
||||
|
||||
#### ApproveTx / `ui_approveTx`
|
||||
#### ApproveTx / `ui_approveTx` {#approvetx}
|
||||
|
||||
Invoked when there's a transaction for approval.
|
||||
|
||||
|
@ -656,7 +656,7 @@ One which has missing `to`, but with no `data`:
|
|||
}
|
||||
```
|
||||
|
||||
#### ApproveListing / `ui_approveListing`
|
||||
#### ApproveListing / `ui_approveListing` {#approvelisting}
|
||||
|
||||
Invoked when a request for account listing has been made.
|
||||
|
||||
|
@ -689,7 +689,7 @@ Invoked when a request for account listing has been made.
|
|||
}
|
||||
```
|
||||
|
||||
#### ApproveSignData / `ui_approveSignData`
|
||||
#### ApproveSignData / `ui_approveSignData` {#approvesigndata}
|
||||
|
||||
##### Sample call
|
||||
|
||||
|
@ -720,7 +720,7 @@ Invoked when a request for account listing has been made.
|
|||
}
|
||||
```
|
||||
|
||||
#### ApproveNewAccount / `ui_approveNewAccount`
|
||||
#### ApproveNewAccount / `ui_approveNewAccount` {#approvenewaccount}
|
||||
|
||||
Invoked when a request for creating a new account has been made.
|
||||
|
||||
|
@ -743,7 +743,7 @@ Invoked when a request for creating a new account has been made.
|
|||
}
|
||||
```
|
||||
|
||||
#### ShowInfo / `ui_showInfo`
|
||||
#### ShowInfo / `ui_showInfo` {#showinfo}
|
||||
|
||||
The UI should show the info (a single message) to the user. Does not expect response.
|
||||
|
||||
|
@ -758,7 +758,7 @@ The UI should show the info (a single message) to the user. Does not expect resp
|
|||
}
|
||||
```
|
||||
|
||||
#### ShowError / `ui_showError`
|
||||
#### ShowError / `ui_showError` {#showerror}
|
||||
|
||||
The UI should show the error (a single message) to the user. Does not expect response.
|
||||
|
||||
|
@ -771,7 +771,7 @@ The UI should show the error (a single message) to the user. Does not expect res
|
|||
}
|
||||
```
|
||||
|
||||
#### OnApprovedTx / `ui_onApprovedTx`
|
||||
#### OnApprovedTx / `ui_onApprovedTx` {#onapprovedtx}
|
||||
|
||||
`OnApprovedTx` is called when a transaction has been approved and signed. The call contains the return value that will be sent to the external caller. The return value from this method is ignored - the reason for having this callback is to allow the ruleset to keep track of approved transactions.
|
||||
|
||||
|
@ -806,7 +806,7 @@ Example call:
|
|||
}
|
||||
```
|
||||
|
||||
#### OnSignerStartup / `ui_onSignerStartup`
|
||||
#### OnSignerStartup / `ui_onSignerStartup` {#onsignerstartup}
|
||||
|
||||
This method provides the UI with information about what API version the signer uses (both internal and external) as well as build-info and external API,
|
||||
in k/v-form.
|
||||
|
@ -831,7 +831,7 @@ Example call:
|
|||
}
|
||||
```
|
||||
|
||||
#### OnInputRequired / `ui_onInputRequired`
|
||||
#### OnInputRequired / `ui_onInputRequired` {#oninputrequired}
|
||||
|
||||
Invoked when Clef requires user input (e.g. a password).
|
||||
|
||||
|
|
|
@ -9,11 +9,11 @@ However, using the `--unlock` flag is generally a highly dangerous thing to do b
|
|||
|
||||
Clef provides a way to safely circumvent `--unlock` while maintaining a enough automation for the network to be useable.
|
||||
|
||||
## Prerequisites
|
||||
## Prerequisites {#prerequisites}
|
||||
|
||||
It is useful to have basic knowledge of private networks and Clef. These topics are covered on our [private networks](/docs/developers/geth-developer/private-network) and [Introduction to Clef](/docs/tools/Clef/introduction) pages.
|
||||
|
||||
## Prepping a Clique network
|
||||
## Prepping a Clique network {#prepping-clique-network}
|
||||
|
||||
First of all, set up a rudimentary testnet to have something to sign. Create a new keystore (password `testtesttest`)
|
||||
|
||||
|
@ -76,7 +76,7 @@ INFO [06-16|11:14:54.125] Successfully wrote genesis state database=ligh
|
|||
|
||||
At this point a Geth has been initiated with a genesis configuration.
|
||||
|
||||
## Prepping Clef
|
||||
## Prepping Clef {#prepping-clef}
|
||||
|
||||
In order to make use of `clef` for signing:
|
||||
|
||||
|
@ -107,7 +107,7 @@ You should treat 'masterseed.json' with utmost secrecy and make a backup of it!
|
|||
|
||||
After this operation, `clef` has it's own vault where it can store secrets and attestations.
|
||||
|
||||
## Storing passwords in `clef`
|
||||
## Storing passwords in `clef` {#storing-passwords}
|
||||
|
||||
With that done, `clef` can be made aware of the password. To do this `setpw <address>` is invoked to store a password for a given address. `clef` asks for the password, and it also asks for the master-password, in order to update and store the new secrets inside the vault.
|
||||
|
||||
|
@ -125,7 +125,7 @@ INFO [06-16|11:27:09.153] Credential store updated set=0x9CD932F
|
|||
|
||||
At this point, if Clef is used as a sealer, each block would require manual approval, but without needing to provide the password.
|
||||
|
||||
### Testing stored password
|
||||
### Testing stored password {#testing-stored-password}
|
||||
|
||||
To test that the stored password is correct and being properly handled by Clef, first start `clef`:
|
||||
|
||||
|
@ -188,7 +188,7 @@ INFO [06-16|11:36:46.714] Successfully sealed new block number=1 seal
|
|||
|
||||
This mode of operation offers quite a poor UX because each block to be sealed requires manual approval. That is fixed in the following section.
|
||||
|
||||
## Using rules to approve blocks
|
||||
## Using rules to approve blocks {#using-rules}
|
||||
|
||||
Clef rules allow a piece of Javascript take over the Approve/Deny decision. The Javascript snippet has access to the same information as the manual operator.
|
||||
|
||||
|
@ -339,7 +339,7 @@ DEBUG[06-16|14:20:33.584] Served account_signData reqid=5 durat
|
|||
|
||||
```
|
||||
|
||||
## Refinements
|
||||
## Refinements {#refinements}
|
||||
|
||||
If an attacker find the Clef "external" interface (which would only happen if you start it with `http` enabled), they
|
||||
|
||||
|
@ -392,7 +392,7 @@ DEBUG[06-16|22:26:45.317] Served account_signData reqid=4 durat
|
|||
|
||||
This might be a bit over-the-top, security-wise, and may cause problems if, for some reason, a clique-deadlock needs to be resolved by rolling back and continuing on a side-chain. It is mainly meant as a demonstration that rules can use Javascript and statefulness to construct very intricate signing logic.
|
||||
|
||||
## TLDR quick-version
|
||||
## TLDR quick-version {#tldr-version}
|
||||
|
||||
Creation and attestation is a one-off event:
|
||||
|
||||
|
@ -434,6 +434,6 @@ clef --keystore ./ddir/keystore \
|
|||
|
||||
For Geth, the only change is to provide `--signer <path to clef ipc>`.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Clef can be used as a signer that automatically seals Clique blocks. This is a much more secure option than unlocking accounts using Geth's built-in account manager.
|
||||
|
|
|
@ -3,11 +3,11 @@ title: Communication data types
|
|||
description: The data types used by the Clef APIs
|
||||
---
|
||||
|
||||
## UI Client interface
|
||||
## UI Client interface {#ui-client-interface}
|
||||
|
||||
These data types are defined in the channel between Clef and the UI
|
||||
|
||||
### SignDataRequest
|
||||
### SignDataRequest {#signdatarequest}
|
||||
|
||||
SignDataRequest contains information about a pending request to sign some data. The data to be signed can be of various types, defined by content-type. Clef has done most of the work in canonicalizing and making sense of the data, and it's up to the UI to present the user with the contents of the `message`
|
||||
|
||||
|
@ -36,7 +36,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### SignDataResponse - approve
|
||||
### SignDataResponse - approve {#signdataresponse-approve}
|
||||
|
||||
Response to SignDataRequest
|
||||
|
||||
|
@ -48,7 +48,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### SignDataResponse - deny
|
||||
### SignDataResponse - deny {#signdataresponse-deny}
|
||||
|
||||
Response to SignDataRequest
|
||||
|
||||
|
@ -60,7 +60,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### SignTxRequest
|
||||
### SignTxRequest {#signtxrequest}
|
||||
|
||||
SignTxRequest contains information about a pending request to sign a transaction. Aside from the transaction itself, there is also a `call_info`-struct. That struct contains messages of various types, that the user should be informed of.
|
||||
|
||||
|
@ -101,7 +101,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### SignTxResponse - approve
|
||||
### SignTxResponse - approve {#signtxresponse-approve}
|
||||
|
||||
Response to request to sign a transaction. This response needs to contain the `transaction`, because the UI is free to make modifications to the transaction.
|
||||
|
||||
|
@ -122,7 +122,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### SignTxResponse - deny
|
||||
### SignTxResponse - deny {#signtxresponse-deny}
|
||||
|
||||
Response to SignTxRequest. When denying a request, there's no need to provide the transaction in return
|
||||
|
||||
|
@ -143,7 +143,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### OnApproved - SignTransactionResult
|
||||
### OnApproved - SignTransactionResult {#onapproved-signtransactionresult}
|
||||
|
||||
SignTransactionResult is used in the call `clef` -> `OnApprovedTx(result)`
|
||||
|
||||
|
@ -175,7 +175,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### UserInputRequest
|
||||
### UserInputRequest {#userinputrequest}
|
||||
|
||||
Sent when clef needs the user to provide data. If 'password' is true, the input field should be treated accordingly (echo-free)
|
||||
|
||||
|
@ -189,7 +189,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### UserInputResponse
|
||||
### UserInputResponse {#userinputresponse}
|
||||
|
||||
Response to UserInputRequest
|
||||
|
||||
|
@ -201,7 +201,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### ListRequest
|
||||
### ListRequest {#listrequest}
|
||||
|
||||
Sent when a request has been made to list addresses. The UI is provided with the full `account`s, including local directory names. Note: this information is not passed back to the external caller, who only sees the `address`es.
|
||||
|
||||
|
@ -229,7 +229,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### ListResponse
|
||||
### ListResponse {#listresponse}
|
||||
|
||||
Response to list request. The response contains a list of all addresses to show to the caller. Note: the UI is free to respond with any address the caller, regardless of whether it exists or not
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ Because the rules are Javascript files they can be customized to implement any a
|
|||
|
||||
This page will explain how rules are implemented in Clef and how best to manage credentials when automatic rulesets are enabled.
|
||||
|
||||
## Rule Implementation
|
||||
## Rule Implementation {#rule-implementation}
|
||||
|
||||
The ruleset engine acts as a gatekeeper to the command line interface - it auto-approves any requests that meet the conditions defined in a set of authenticated rule files. This prevents the user from having to manually approve or reject every request - instead they can define common patterns in a rule file and abstract that task away to the ruleset engine. The general architecture is as follows:
|
||||
|
||||
|
@ -83,7 +83,7 @@ There are some additional noteworthy implementation details that are important f
|
|||
- The regular expression engine (re2/regexp) in Otto VM is not fully compatible with the [ECMA5 specification](https://tc39.es/ecma262/#sec-intro).
|
||||
- [Strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) is not supported. "use strict" will parse but it does nothing.
|
||||
|
||||
## Credential management
|
||||
## Credential management {#credential-management}
|
||||
|
||||
The ability to auto-approve transaction requires that the signer has the necessary credentials, i.e. account passwords, to decrypt keyfiles. These are stored encrypted as follows:
|
||||
|
||||
|
@ -98,13 +98,13 @@ The `signer` uses the `seed` to:
|
|||
|
||||
`config.json` stores the hashes of any attested rulesets. `credentials.json` stores encrypted account passwords. The masterseed is required to decrypt these files. The decrypted account passwords can then be used to decrypt keyfiles.
|
||||
|
||||
## Security
|
||||
## Security {#security}
|
||||
|
||||
### The Javascript VM
|
||||
### The Javascript VM {#javascript-vm}
|
||||
|
||||
The downside of the very flexible rule implementation included in Clef is that the `signer` binary needs to contain a Javascript engine. This is an additional attack surface. The only viable attack is for an adversary to somehow extract cryptographic keys from memory during the Javascript VM execution. The hash-based rule attestation condition means the actual Javascript code executed by the Javascript engine is not a viable attack surface -- since if the attacker can control the ruleset, a much simpler attack would be to surreptitiously insert an attested "always-approve" rule instead of attempting to exploit the Javascript virtual machine. The Javascript engine is quite simple to implement and there are currently no known security vulnerabilities, not have there been any security problems identified for the similar Javascript VM implemented in Geth.
|
||||
|
||||
### Writing rules
|
||||
### Writing rules {#writing-rules}
|
||||
|
||||
Since the user has complete freedom to write custom rules, it is plausible that those rules could create unintended security vulnerabilities. This can only really be protected by coding very carefully and trying to test rulesets (e.g. on a private testnet) before implementing them on a public network.
|
||||
|
||||
|
@ -112,13 +112,13 @@ Javascript is very flexible but also easy to write incorrectly. For example, use
|
|||
|
||||
It’s unclear whether any other language would be more secure - there is alwas the possibility of implementing an insecure rule.
|
||||
|
||||
### Credential security
|
||||
### Credential security {#credential-security}
|
||||
|
||||
Clef implements a secure, encrypted vault for storing sensitive data. This vault is encrypted using a `masterseed` which the user is responsible for storing and backing up safely and securely. Since this `masterseed` is used to decrypt the secure vault, and its security is not handled by Clef, it could represent a security vulnerability if the user does not implement best practise in keeping it safe.
|
||||
|
||||
The same is also true for keys. Keys are not stored by Clef, they are only accessed using account passwords that Clef does store in its vault. The keys themselves are stored in an external `keystore` whose security is the responsibility of the user. If the keys are compromised, the account is not safe irrespective of the security benefits derived from Clef.
|
||||
|
||||
## Ruleset examples
|
||||
## Ruleset examples {#ruleset-examples}
|
||||
|
||||
Below are some examples of `ruleset.js` files.
|
||||
|
||||
|
@ -236,6 +236,6 @@ function OnApprovedTx(resp) {
|
|||
}
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Rules are sets of conditions encoded in Javascript files that enable certain actions to be auto-approved by Clef. This page outlined the implementation details and security considerations that will help to build suitrable ruleset files. See the [Clef Github](https://github.com/ethereum/go-ethereum/tree/master/cmd/clef) for further reading.
|
||||
|
|
|
@ -6,9 +6,9 @@ description: More advanced ways to set up Clef for additional security
|
|||
Clef is a signer and account management tool that is external to Geth. This means it can be run as a separate process or even on a separate machine to the one running Geth, for example on secure hardware that is not connected to any external network, or on secure virtual machines.
|
||||
This page describes how Clef can be used with Qubes OS to provide a more secure setup than a normal laptop. Using Clef with USBArmory hardware is also briefly described.
|
||||
|
||||
## Qubes OS
|
||||
## Qubes OS {#qubes-os}
|
||||
|
||||
### Background
|
||||
### Background {#background}
|
||||
|
||||
The Qubes operating system configures a set of virtual machines for different purposes such as:
|
||||
|
||||
|
@ -27,11 +27,11 @@ A couple of dedicated virtual machines handle externalities:
|
|||
|
||||
The goal of this document is to describe how we can set up Clef to provide secure transaction signing from a `vault` vm, to another networked qube which runs Dapps.
|
||||
|
||||
### Setup
|
||||
### Setup {#setup}
|
||||
|
||||
There are two ways that this can be achieved: integrated via Qubes or integrated via networking.
|
||||
|
||||
#### 1. Qubes Integrated
|
||||
#### 1. Qubes Integrated {#qubes-integrated}
|
||||
|
||||
Qubes provides a facility for inter-qubes communication via `qrexec`. A qube can request to make a cross-qube RPC request to another qube. The OS then asks the user if the call is permitted.
|
||||
|
||||
|
@ -41,7 +41,7 @@ A policy-file can be created to allow such interaction. On the `target` domain,
|
|||
|
||||
This is how [Split GPG](https://www.qubes-os.org/doc/split-gpg/) is implemented. Clef can be set up in the same way:
|
||||
|
||||
##### Server
|
||||
##### Server {#server}
|
||||
|
||||
![Clef via qrexec](/images/docs/clef_qubes_qrexec.png)
|
||||
|
||||
|
@ -80,7 +80,7 @@ sudo chmod +x /etc/qubes-rpc/ qubes.Clefsign
|
|||
|
||||
This setup uses [gtksigner](https://github.com/holiman/gtksigner), which is a very minimal GTK-based UI that works well with minimal requirements.
|
||||
|
||||
##### Client
|
||||
##### Client {#client}
|
||||
|
||||
On the `client` qube, a listener is required to receive the request from the Dapp, and proxy it.
|
||||
|
||||
|
@ -109,7 +109,7 @@ with socketserver.TCPServer(("",PORT), Dispatcher) as httpd:
|
|||
httpd.serve_forever()
|
||||
```
|
||||
|
||||
#### Testing
|
||||
#### Testing {#testing}
|
||||
|
||||
To test the flow, with `debian-work` as the `target`:
|
||||
|
||||
|
@ -142,7 +142,7 @@ Make the request over http (`client` qube):
|
|||
|
||||
And it should show the same popups again.
|
||||
|
||||
##### Pros and cons
|
||||
##### Pros and cons {#pros-and-cons}
|
||||
|
||||
The benefits of this setup are:
|
||||
|
||||
|
@ -161,13 +161,13 @@ However, it comes with a couple of drawbacks:
|
|||
- One qubes-specific where the user specifies the `target` vm
|
||||
- One clef-specific to approve the transaction
|
||||
|
||||
#### 2. Network integrated
|
||||
#### 2. Network integrated {#network-integrated}
|
||||
|
||||
The second way to set up Clef on a qubes system is to allow networking, and have Clef listen to a port which is accessible from other qubes.
|
||||
|
||||
![Clef via http](/images/docs/clef_qubes_http.png)
|
||||
|
||||
## USBArmory
|
||||
## USBArmory {#usb-armory}
|
||||
|
||||
The [USB armory](https://inversepath.com/usbarmory) is an open source hardware design with an 800 MHz ARM processor. It is a pocket-sized computer. When inserted into a laptop, it identifies itself as a USB network interface, basically adding another network to your computer that can be used to SSH into the device.
|
||||
|
||||
|
@ -175,6 +175,6 @@ Running Clef off a USB armory means that the armory can be used as a very versat
|
|||
|
||||
Needless to say, while this model should be fairly secure against remote attacks, an attacker with physical access to the USB Armory would trivially be able to extract the contents of the device filesystem.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page introduced two ways to setup Clef that give additional security compared to running on a normal laptop.
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Beginner tutorial for using Clef as an external signer for Geth
|
|||
|
||||
This page provides a step-by-step walkthrough tutorial demonstrating some common uses of Clef. This includes manual approvals and automated rules. Clef is presented both as a standalone general signer with requests made via RPC and also as a backend signer for Geth.
|
||||
|
||||
## Initializing Clef
|
||||
## Initializing Clef {#initializing-clef}
|
||||
|
||||
First things first, Clef needs to store some data itself. Since that data might be sensitive (passwords, signing rules, accounts), Clef's entire storage is encrypted. To support encrypting data, the first step is to initialize Clef with a random master seed, itself too encrypted with a password:
|
||||
|
||||
|
@ -46,7 +46,7 @@ You should treat 'masterseed.json' with utmost secrecy and make a backup of it!
|
|||
|
||||
_For readability purposes, we'll remove the WARNING printout, user confirmation and the unlocking of the master seed in the rest of this document._
|
||||
|
||||
## Remote interactions
|
||||
## Remote interactions {#remote-interactions}
|
||||
|
||||
This tutorial will use Clef with Geth on the Goerli testnet. The accounts used will be in the Goerli keystore with the path `~/go-ethereum/goerli-data/keystore`. The tutorial assumes there are two accounts in this keystore. Instructions for creating accounts can be found on the [Account managament page](/docs/interface/managing-your-accounts). Note that Clef can also interact with hardware wallets, although that is not demonstrated here.
|
||||
|
||||
|
@ -198,7 +198,7 @@ Approve? [y/N]
|
|||
|
||||
Approving this transaction causes Clef to prompt the user to provide the password for the sender account. Providing the password enables the transaction to be signed and sent to Geth for broadcasting to the network. The details of the signed transaction are displayed in the console. Account passwords can also be stored in Clef's encrypted vault so that they do not have to be manually entered - [more on this below](#account-passwords).
|
||||
|
||||
## Automatic rules
|
||||
## Automatic rules {#automatic-rules}
|
||||
|
||||
For most users, manually confirming every transaction is the right way to use Clef because a human-in-the-loop can review every action. However, there are cases when it makes sense to set up some rules which permit Clef to sign a transaction without prompting the user.
|
||||
For example, well defined rules such as:
|
||||
|
@ -206,7 +206,7 @@ For example, well defined rules such as:
|
|||
- Auto-approve transactions with Uniswap v2, with value between 0.1 and 0.5 ETH per 24h period
|
||||
- Auto-approve transactions to address `0xD9C9Cd5f6779558b6e0eD4e6Acf6b1947E7fA1F3` as long as gas < 44k and gasPrice < 80Gwei can be encoded and interpreted by Clef's built-in ruleset engine.
|
||||
|
||||
### Rule files
|
||||
### Rule files {#rule-files}
|
||||
|
||||
Rules are implemented as Javascript code in `js` files. The ruleset engine includes the same methods as the JSON_RPC defined in the [UI Protocol](/docs/_clef/datatypes). The following code snippet demonstrates a rule file that approves a transaction if it satisfies the following conditions:
|
||||
|
||||
|
@ -257,7 +257,7 @@ There are three possible outcomes to this ruleset that are handled in different
|
|||
| Unexpected value | Pass decision to UI for manual approval |
|
||||
| Nothing | Pass decision to UI for manual approval |
|
||||
|
||||
### Attestations
|
||||
### Attestations {#attestations}
|
||||
|
||||
Clef will not just accept and run arbitrary scripts - that would create an attack vector because a malicious party could change the rule file.Instead, the user explicitly _attests_ to a rule file, which involves injecting the file's SHA256 hash into Clef's secure store. The following code snippet shows how to calculate a SHA256 hash for a file named `rules.js` and pass it to Clef. Note that Clef will prompt the user to provide the master password because the Clef store has to be decrypted in order to add the attestation to it.
|
||||
|
||||
|
@ -271,7 +271,7 @@ clef attest 645b58e4f945e24d0221714ff29f6aa8e860382ced43490529db1695f5fcc71c
|
|||
|
||||
Once this attestation has been added to the Clef store, it can be used to automatically approve interactions that satisfy the conditions encoded in `rules.js` in Clef.
|
||||
|
||||
### Account passwords
|
||||
### Account passwords {#account-passwords}
|
||||
|
||||
The rules described in `rules.js` above require access to the accounts in the Clef keystore which are protected by user-defined passwords. The signer therefore requires access to these passwords in order to automatically unlock the keystore and sign data and transactions using the accounts.
|
||||
|
||||
|
@ -295,7 +295,7 @@ INFO [07-01|14:05:56.031] Credential store updated key=0xd9c9cd5f6779558b6e0ed
|
|||
|
||||
Note that Clef does not really 'unlock' an account, it just abstracts the process of providing the password away from the end-user in specific, predefined scenarios. If an account password exists in the Clef vault and the rule evaluates to "Approve" then Clef decrypts the password, uses it to decrypt the key, does the requested signing and then re-locks the account.
|
||||
|
||||
### Implementing rules
|
||||
### Implementing rules {#implementing-rules}
|
||||
|
||||
Clef can be instructed to run an attested rule file simply by passing the path to `rules.js` to the `--rules` flag:
|
||||
|
||||
|
@ -357,7 +357,7 @@ eth.sendTransaction(tx);
|
|||
|
||||
These latter two transactions, that do not satisfy the encoded rules in `rules.js`, are not automatically approved, but instead pass the decision back to the UI for manual approval by the user.
|
||||
|
||||
### Summary of basic usage
|
||||
### Summary of basic usage {#summary-of-usage}
|
||||
|
||||
To summarize, the steps required to run Clef with an automated ruleset that requires account access is as follows:
|
||||
|
||||
|
@ -373,7 +373,7 @@ To summarize, the steps required to run Clef with an automated ruleset that requ
|
|||
|
||||
**6)** Make requests directly to Clef using the external API or connect to Geth by passing `--signer=<path to clef.ipc>` at Geth startup
|
||||
|
||||
## More rules
|
||||
## More rules {#more-rules}
|
||||
|
||||
Since rules are defined as Javascript code, rulesets of arbitrary complexity can be created and they can impose conditions on any part of a transaction, not only the recipient and value. A simple example is implementing a "whitelist" of recipients where transactions that have those
|
||||
accounts in the `to` field are automatically signed (for example perhaps transactions between a user's own accounts might be whitelisted):
|
||||
|
@ -505,7 +505,7 @@ t=2022-07-01T15:52:23+0300 lvl=info msg=SignData api=signer type=response data
|
|||
|
||||
More examples, including a ruleset for a rate-limited window, are available on the [Clef Github](https://github.com/ethereum/go-ethereum/blob/master/cmd/clef/rules.md#example-1-ruleset-for-a-rate-limited-window) and on the [Rules page](/docs/tools/Clef/rules).
|
||||
|
||||
## Under the hood
|
||||
## Under the hood {#under-the-hood}
|
||||
|
||||
The examples on this page have provided step-by-step instructions for various operations using Clef. However, they have not provided much detail as to what is happening under the hood. This section will provide some more details about how Clef organizes itself locally.
|
||||
|
||||
|
@ -563,14 +563,14 @@ cat ~/.clef/02f90c0603f4f2f60188/config.json
|
|||
{"0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3": {"iv": "6SC062CfaUW8uSqH","c":"C+S5kaJyrarrxrAESs4EmPjL5zmg5tRh0Q=="}}
|
||||
```
|
||||
|
||||
## Geth integration
|
||||
## Geth integration {#geth-integration}
|
||||
|
||||
This tutorial has bounced back and forth between demonstrating Clef as a standalone tool by making 'manual` JSON RPC requests from the terminal and integrating it as a backend singer for Geth. Using Clef for account management is considered best practise for Geth users because of the additional
|
||||
security benefits it offers over and above what it offered by Geth's built-in accounts module. Clef is far more flexible and composable than Geth's built-in account management tool and can interface directly with hardware wallets, while Apps and wallets can request signatures directly from Clef.
|
||||
|
||||
Ultimately, the goal is to deprecate Geth's account management tools completely and replace them with Clef. Until then, users are simply encouraged to choose to use Clef as an optional backend signer for Geth. In addition to the examples on this page, the [Getting started tutorial](/docs/_getting-started/index) also demonstrates Clef/Geth integration.
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page includes step-by-step instructions for basic and intermediate uses of Clef, including using it as a standalone app and a backend signer for Geth. Further information is available on our other Clef pages, including [Introduction](/docs/clef/introduction), [Setup](/docs/clef/setup),
|
||||
[Rules](/docs/clef/rules), [Communication Datatypes](/docs/clef/datatypes) and [Communication APIs](/docs/clef/apis). Also see the [Clef Github](https://github.com/ethereum/go-ethereum/tree/master/cmd/clef) for further reading.
|
||||
|
|
|
@ -21,7 +21,7 @@ To debug and develop these networking components, Geth includes a command line t
|
|||
|
||||
This page will outline some of `devp2p`s built-in tools.
|
||||
|
||||
## ENR Decoding
|
||||
## ENR Decoding {#enr-decoding}
|
||||
|
||||
Ethereum Node Records can be decoded, verified and displayed to the terminal using `enrdump`. It takes the ENR in its encoded form, which is the base64 encoding of its RLP representation. A decoded human-readable text representation is displayed.
|
||||
|
||||
|
@ -45,7 +45,7 @@ Record has sequence number 7 and 7 key/value pairs.
|
|||
|
||||
Read more on [Ethereum Node Records](https://ethereum.org/en/developers/docs/networking-layer/network-addresses/#enr) or browse the [specs](https://github.com/ethereum/devp2p/blob/591edbd36eb57280384d07373a818c00bddf3b31/enr.md).
|
||||
|
||||
## Node Key Management
|
||||
## Node Key Management {#node-key-management}
|
||||
|
||||
The `devp2p key ...` command family deals with node key files.
|
||||
|
||||
|
@ -53,7 +53,7 @@ Run `devp2p key generate mynode.key` to create a new node key in the `mynode.key
|
|||
|
||||
Run `devp2p key to-enode mynode.key -ip 127.0.0.1 -tcp 30303` to create an enode:// URL corresponding to the given node key and address information.
|
||||
|
||||
## Maintaining DNS Discovery Node Lists
|
||||
## Maintaining DNS Discovery Node Lists {#maintaining-dns-discovery-lists}
|
||||
|
||||
The devp2p command can create and publish DNS discovery node lists.
|
||||
|
||||
|
@ -67,7 +67,7 @@ Run `devp2p dns to-route53 <directory>` to publish a tree to Amazon Route53.
|
|||
|
||||
More information about these commands can be found in the [DNS Discovery Setup Guide](/docs/developers/dns-discovery-setup).
|
||||
|
||||
## Node Set Utilities
|
||||
## Node Set Utilities {#node-set-utilities}
|
||||
|
||||
There are several commands for working with JSON node set files. These files are generated by the discovery crawlers and DNS client commands. Node sets also used as the input of the DNS deployer commands.
|
||||
|
||||
|
@ -88,7 +88,7 @@ For example, given a node set in `nodes.json`, you could create a filtered set c
|
|||
devp2p nodeset filter nodes.json -eth-network mainnet -snap -limit 20
|
||||
```
|
||||
|
||||
## Discovery v4 Utilities
|
||||
## Discovery v4 Utilities {#discovery-v4-utilities}
|
||||
|
||||
The `devp2p discv4 ...` command family deals with the [Node Discovery v4](https://github.com/ethereum/devp2p/tree/master/discv4.md) protocol.
|
||||
|
||||
|
@ -98,7 +98,7 @@ Run `devp2p discv4 resolve <enode/ENR>` to find the most recent node record of a
|
|||
|
||||
Run `devp2p discv4 crawl <nodes.json path>` to create or update a JSON node set.
|
||||
|
||||
## Discovery v5 Utilities
|
||||
## Discovery v5 Utilities {#discovery-v5-utilities}
|
||||
|
||||
The `devp2p discv5 ...` command family deals with the [Node Discovery v5](https://github.com/ethereum/devp2p/tree/master/discv5/discv5.md) protocol. This protocol is currently under active development.
|
||||
|
||||
|
@ -110,7 +110,7 @@ Run `devp2p discv5 listen` to run a Discovery v5 node.
|
|||
|
||||
Run `devp2p discv5 crawl <nodes.json path>` to create or update a JSON node set containing discv5 nodes.
|
||||
|
||||
## Discovery Test Suites
|
||||
## Discovery Test Suites {#discovery-test-suites}
|
||||
|
||||
The devp2p command also contains interactive test suites for Discovery v4 and Discovery v5. To run these tests a networking environment must be set up with two separate UDP listening addresses are available on the same machine. The two listening addresses must also be routed such
|
||||
that they are able to reach the node you want to test.
|
||||
|
@ -129,7 +129,7 @@ Either test suite can then be run as follows:
|
|||
|
||||
3. Start the test by running `devp2p discv5 test -listen1 127.0.0.1 -listen2 127.0.0.2 $NODE`.
|
||||
|
||||
## Eth Protocol Test Suite
|
||||
## Eth Protocol Test Suite {#eth-protocol-test-suite}
|
||||
|
||||
The Eth Protocol test suite is a conformance test suite for the [eth protocol](https://github.com/ethereum/devp2p/blob/master/caps/eth.md).
|
||||
|
||||
|
@ -151,7 +151,7 @@ devp2p rlpx eth-test <enode> cmd/devp2p/internal/ethtest/testdata/chain.rlp cmd/
|
|||
|
||||
Repeat the above process (re-initialising the node) in order to run the Eth Protocol test suite again.
|
||||
|
||||
### Eth66 Test Suite
|
||||
### Eth66 Test Suite {#eth66-test-suite}
|
||||
|
||||
The Eth66 test suite is also a conformance test suite for the eth 66 protocol version specifically. To run the eth66 protocol test suite, initialize a Geth node as described above and run the following command, replacing `<enode>` with the enode of the Geth node:
|
||||
|
||||
|
@ -159,6 +159,6 @@ The Eth66 test suite is also a conformance test suite for the eth 66 protocol ve
|
|||
devp2p rlpx eth66-test <enode> cmd/devp2p/internal/ethtest/testdata/chain.rlp cmd/devp2p/internal/ethtest/testdata/genesis.json
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
This page introduced the DevP2P stack that defines Ethereum's peer-to-peer network and the `devp2p` command line tool that comes bundled with Geth. The `devp2p` tools enables Geth developers to work on the peer-to-peer network.
|
||||
|
|
|
@ -8,7 +8,7 @@ The user is guided through the process by a command line wizard.
|
|||
|
||||
Puppeth comes bundled with Geth. The binary for Puppeth is built along with the other command line tools when the user runs `make all`. By default the binaries are saved to `build/bin`. This page demonstrates how to start a private proof-of-authority network with all the nodes running on the local machine. Other configurations are also possible, for example nodes can be spread over multiple (virtual) machines and the consensus mechanism can be proof-of-work.
|
||||
|
||||
## Creating accounts
|
||||
## Creating accounts {#creating-accounts}
|
||||
|
||||
To run a Clique network, authorized nodes must seal each block. This requires accounts to exist that can be pre-authorized in the genesis block. These accounts should be created before Puppeth is started. The accounts can be created using Geth's built in account manager as follows:
|
||||
|
||||
|
@ -22,7 +22,7 @@ Geth will prompt for a password. Once provided, the public address of the new ac
|
|||
|
||||
See more on the [account management pages](/docs/fundamentals/account-management).
|
||||
|
||||
## Starting Puppeth
|
||||
## Starting Puppeth {#starting-puppeth}
|
||||
|
||||
Starting Puppeth is as easy as running `puppeth` in the terminal:
|
||||
|
||||
|
@ -117,7 +117,7 @@ Which folder to save the genesis specs into? (default = current)
|
|||
|
||||
At this point a genesis configuration has been created and backed up. There are a few more componments that are required to start the network.
|
||||
|
||||
## Network components
|
||||
## Network components {#network-components}
|
||||
|
||||
Puppeth includes wizards for adding several network components:
|
||||
|
||||
|
@ -132,35 +132,35 @@ Puppeth includes wizards for adding several network components:
|
|||
|
||||
These are all accessed by starting Puppeth and selecting `4. Deploy network components` from the main menu. They should be deployed in the numerical order in which they are listed in the `Network components` submenu.
|
||||
|
||||
### Ethstats
|
||||
### Ethstats {#ethstats}
|
||||
|
||||
Ethstats is a network monitoring service. The Ethstats server must already be installed (see [instructions](https://github.com/cubedro/eth-netstats)) and running so that its IP address can be provided to Puppeth. The IP address of each node is also required. The wizard guides the user through providing the IP addresses and ports for Ethstats and the local nodes and setting a password for the Ethstats API.
|
||||
|
||||
### Bootnodes
|
||||
### Bootnodes {#bootnodes}
|
||||
|
||||
Bootnodes are nodes with hardcoded addresses that allow new nodes entering the network to immediately find peers to connect to. This makes peer discovery faster. The wizard guides the user through providing IP addresses for nodes on the network that will be used as bootnodes.
|
||||
|
||||
### Sealer
|
||||
### Sealer {#sealer}
|
||||
|
||||
The sealer nodes must be specified. These validate the network by sealing blocks. The wizard prompts the user to provide the IP addresses for the sealer nodes along with their keyfiles and unlock passwords. Some additional information is also set for the bootnodes including their gas limit - the higher the gas limit the more work the node has to do to validate each block. To match Ethereum set it to 15,000,000. The gas price can be anything, but since it is a private test network it may as well be small, say 1 GWei.
|
||||
|
||||
Puppeth will display the details of each node in a table in the terminal.
|
||||
|
||||
### Explorer
|
||||
### Explorer {#explorer}
|
||||
|
||||
For proof-of-work networks a block explorer akin to [etherscan](etherscan.io) can be created using the Puppeth wizard.
|
||||
|
||||
### Faucet
|
||||
### Faucet {#faucet}
|
||||
|
||||
A faucet is an app that allows accounts to request ether to be sent to them. This can be created easily by following the wizard. The wizard prompts the user for details related to which node will act as a server for the faucet, how much ether to release per request, intervals between releases and some optional security features.
|
||||
|
||||
### Dashboard
|
||||
### Dashboard {#dashboard}
|
||||
|
||||
The dashboard wizard pulls together the pieces from the already-defined network components into a single dashboard that can be navigated to in a web browser. The wizard guides the user through the necessary steps. Optionally, the explorer and faucet apps can be deployed here too.
|
||||
|
||||
The dashboard can then be viewed by navigating to the node's ip address and the defined port in a web browser.
|
||||
|
||||
## Starting the network
|
||||
## Starting the network {#starting-network}
|
||||
|
||||
Start instances of Geth for each node
|
||||
|
||||
|
@ -168,7 +168,7 @@ Start instances of Geth for each node
|
|||
geth --datadir Node1 --port 30301 --bootnodes <enr> --networkid <testnetwork ID> -unlock <node 1 address> --mine
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Summary {#summary}
|
||||
|
||||
Puppeth is a command line wizard that guides a user through the various stages of setting up a private network using proof-of-authority or proof-of-work consensus engine. Various network components can be added that optimize the network or enable network monitoring.
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# https://docs.netlify.com/integrations/frameworks/next-js/incremental-static-regeneration/
|
||||
|
||||
[functions]
|
||||
included_files = ["src/**"]
|
|
@ -21,6 +21,8 @@
|
|||
"@mdx-js/react": "^2.1.3",
|
||||
"@next/mdx": "^12.3.0",
|
||||
"algoliasearch": "^4.14.2",
|
||||
"chakra-ui-markdown-renderer": "^4.1.0",
|
||||
"fast-xml-parser": "^4.0.12",
|
||||
"focus-visible": "^5.2.0",
|
||||
"framer-motion": "^7.3.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
|
@ -29,7 +31,8 @@
|
|||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-syntax-highlighter": "^15.5.0"
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"remark-gfm": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
|
@ -1,4 +0,0 @@
|
|||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.1 KiB |
|
@ -1,38 +1,26 @@
|
|||
import { Heading, Link, Stack, Text } from '@chakra-ui/react';
|
||||
import {
|
||||
Flex,
|
||||
Heading,
|
||||
Link,
|
||||
ListItem,
|
||||
OrderedList,
|
||||
Stack,
|
||||
Table,
|
||||
Text,
|
||||
UnorderedList
|
||||
} from '@chakra-ui/react';
|
||||
import NextLink from 'next/link';
|
||||
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { nightOwl } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||
|
||||
import bash from 'react-syntax-highlighter/dist/cjs/languages/prism/bash';
|
||||
import go from 'react-syntax-highlighter/dist/cjs/languages/prism/go';
|
||||
import graphql from 'react-syntax-highlighter/dist/cjs/languages/prism/graphql';
|
||||
import java from 'react-syntax-highlighter/dist/cjs/languages/prism/java';
|
||||
import javascript from 'react-syntax-highlighter/dist/cjs/languages/prism/javascript';
|
||||
import json from 'react-syntax-highlighter/dist/cjs/languages/prism/json';
|
||||
import python from 'react-syntax-highlighter/dist/cjs/languages/prism/python';
|
||||
import sh from 'react-syntax-highlighter/dist/cjs/languages/prism/shell-session';
|
||||
import solidity from 'react-syntax-highlighter/dist/cjs/languages/prism/solidity';
|
||||
import swift from 'react-syntax-highlighter/dist/cjs/languages/prism/swift';
|
||||
import { Code } from './UI/docs';
|
||||
import { textStyles } from '../theme/foundations';
|
||||
|
||||
// syntax highlighting languages supported
|
||||
SyntaxHighlighter.registerLanguage('bash', bash);
|
||||
SyntaxHighlighter.registerLanguage('go', go);
|
||||
SyntaxHighlighter.registerLanguage('graphql', graphql);
|
||||
SyntaxHighlighter.registerLanguage('java', java);
|
||||
SyntaxHighlighter.registerLanguage('javascript', javascript);
|
||||
SyntaxHighlighter.registerLanguage('json', json);
|
||||
SyntaxHighlighter.registerLanguage('python', python);
|
||||
SyntaxHighlighter.registerLanguage('sh', sh);
|
||||
SyntaxHighlighter.registerLanguage('solidity', solidity);
|
||||
SyntaxHighlighter.registerLanguage('swift', swift);
|
||||
|
||||
import { getProgrammingLanguageName } from '../utils';
|
||||
const { header1, header2, header3, header4 } = textStyles;
|
||||
|
||||
const MDXComponents = {
|
||||
// paragraphs
|
||||
p: ({ children }: any) => {
|
||||
return (
|
||||
<Text mb={7} _last={{ mb: 0 }} size='sm' lineHeight={1.5}>
|
||||
<Text mb={7} lineHeight={1.5}>
|
||||
{children}
|
||||
</Text>
|
||||
);
|
||||
|
@ -43,7 +31,7 @@ const MDXComponents = {
|
|||
<NextLink href={href} passHref>
|
||||
<Link
|
||||
isExternal={href.startsWith('http') && !href.includes('geth.ethereum.org')}
|
||||
color='primary'
|
||||
variant='light'
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
|
@ -53,63 +41,74 @@ const MDXComponents = {
|
|||
// headings
|
||||
h1: ({ children }: any) => {
|
||||
return (
|
||||
<Heading as='h1' textAlign='start' fontSize='4xl' mb={5}>
|
||||
<Heading as='h1' textAlign='start' mb={5} {...header1}>
|
||||
{children}
|
||||
</Heading>
|
||||
);
|
||||
},
|
||||
h2: ({ children }: any) => {
|
||||
return (
|
||||
<Heading as='h2' textAlign='start' fontSize='3xl' mb={4}>
|
||||
<Heading as='h2' textAlign='start' mt='16 !important' mb={4} {...header2}>
|
||||
{children}
|
||||
</Heading>
|
||||
);
|
||||
},
|
||||
h3: ({ children }: any) => {
|
||||
return (
|
||||
<Heading as='h3' fontSize='2xl' mt={5} mb={2.5}>
|
||||
<Heading as='h3' mt={5} mb={2.5} {...header3}>
|
||||
{children}
|
||||
</Heading>
|
||||
);
|
||||
},
|
||||
h4: ({ children }: any) => {
|
||||
return (
|
||||
<Heading as='h4' fontSize='lg' mb={2.5}>
|
||||
<Heading as='h4' mb={2.5} {...header4}>
|
||||
{children}
|
||||
</Heading>
|
||||
);
|
||||
},
|
||||
// tables
|
||||
table: ({ children }: any) => (
|
||||
<Flex maxW='min(100%, 100vw)' overflowX='scroll'>
|
||||
<Table
|
||||
variant='striped'
|
||||
colorScheme='greenAlpha'
|
||||
border='1px'
|
||||
borderColor='blackAlpha.50'
|
||||
my={6}
|
||||
size={{ base: 'sm', lg: 'md' }}
|
||||
w='auto'
|
||||
>
|
||||
{children}
|
||||
</Table>
|
||||
</Flex>
|
||||
),
|
||||
// pre
|
||||
pre: ({ children }: any) => {
|
||||
return (
|
||||
<Stack mb={5}>
|
||||
<pre>{children}</pre>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
pre: ({ children }: any) => (
|
||||
<Stack mb={5}>
|
||||
<pre>{children}</pre>
|
||||
</Stack>
|
||||
),
|
||||
// code
|
||||
// code: (code: any) => {
|
||||
// const language = getProgrammingLanguageName(code);
|
||||
|
||||
// return !!code.inline ? (
|
||||
// <Text
|
||||
// as={'span'}
|
||||
// padding='0.125em 0.25em'
|
||||
// color='red.300'
|
||||
// background='code-bg-contrast'
|
||||
// borderRadius='0.25em'
|
||||
// fontFamily='code'
|
||||
// fontSize='sm'
|
||||
// overflowY='scroll'
|
||||
// >
|
||||
// {code.children[0]}
|
||||
// </Text>
|
||||
// ) : (
|
||||
// <Stack style={nightOwl}>
|
||||
// {code.children[0]}
|
||||
// </Stack>
|
||||
// );
|
||||
// }
|
||||
code: ({ children, ...props }: any) => <Code {...props}>{children}</Code>,
|
||||
// list
|
||||
ul: ({ children }: any) => {
|
||||
return (
|
||||
<UnorderedList mb={7} px={4}>
|
||||
{children}
|
||||
</UnorderedList>
|
||||
);
|
||||
},
|
||||
ol: ({ children }: any) => {
|
||||
return (
|
||||
<OrderedList mb={7} px={4}>
|
||||
{children}
|
||||
</OrderedList>
|
||||
);
|
||||
},
|
||||
li: ({ children }: any) => {
|
||||
return <ListItem color='primary'>{children}</ListItem>;
|
||||
}
|
||||
};
|
||||
|
||||
export default MDXComponents;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { Link, Stack, Text } from '@chakra-ui/react';
|
||||
import NextLink, { LinkProps } from 'next/link';
|
||||
|
||||
import { Link as LinkTheme } from "../../theme/components"
|
||||
import { Link as LinkTheme } from '../../theme/components';
|
||||
|
||||
interface Props extends LinkProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ButtonLinkSecondary: React.FC<Props> = ({ href, children, ...restProps}) => {
|
||||
export const ButtonLinkSecondary: React.FC<Props> = ({ href, children, ...restProps }) => {
|
||||
const isExternal: boolean = href.toString().startsWith('http');
|
||||
const variant = LinkTheme.variants["button-link-secondary"]
|
||||
const variant = LinkTheme.variants['button-link-secondary'];
|
||||
return (
|
||||
<Stack sx={{ mt: '0 !important' }} {...variant}>
|
||||
<NextLink href={href} passHref {...restProps}>
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { Table, Thead, Tr, Th, TableContainer, Text, Tbody, Td } from '@chakra-ui/react';
|
||||
import { Link, Table, Thead, Tr, Th, TableContainer, Text, Tbody, Td } from '@chakra-ui/react';
|
||||
import { FC } from 'react';
|
||||
import { ReleaseData } from '../../types';
|
||||
import { getParsedDate } from '../../utils';
|
||||
|
||||
interface Props {
|
||||
columnHeaders: string[];
|
||||
// TODO: update data type
|
||||
data: any;
|
||||
}
|
||||
|
||||
|
@ -41,20 +44,44 @@ export const DataTable: FC<Props> = ({ columnHeaders, data }) => {
|
|||
})}
|
||||
</Tr>
|
||||
</Thead>
|
||||
|
||||
<Tbody>
|
||||
{data.map((item: any, idx: number) => {
|
||||
{data.map((r: ReleaseData, idx: number) => {
|
||||
return (
|
||||
<Tr
|
||||
key={idx}
|
||||
// TODO: Get new background color from nuno for hover
|
||||
transition={'all 0.5s'}
|
||||
_hover={{ background: 'button-bg', transition: 'all 0.5s' }}
|
||||
>
|
||||
{columnHeaders.map((columnHeader, idx) => {
|
||||
// TODO: Make the font size smaller (refer to design system)
|
||||
{Object.entries(r).map((item, idx) => {
|
||||
const objectItems = ['release', 'commit', 'signature'];
|
||||
|
||||
if (objectItems.includes(item[0])) {
|
||||
const label = item[1].label;
|
||||
const url = item[1].url;
|
||||
|
||||
return (
|
||||
<Td key={idx} px={4} textStyle='hero-text-small'>
|
||||
<Link _hover={{ textDecoration: 'none' }} href={url} isExternal>
|
||||
<Text color='primary'>
|
||||
{item[0] === 'commit' ? `${label}...` : label}
|
||||
</Text>
|
||||
</Link>
|
||||
</Td>
|
||||
);
|
||||
}
|
||||
|
||||
if (item[0] === 'published') {
|
||||
return (
|
||||
<Td key={idx} px={4} textStyle='hero-text-small'>
|
||||
<Text>{getParsedDate(item[1])}</Text>
|
||||
</Td>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Td key={idx} px={4} fontSize='13px'>
|
||||
{item[columnHeader.toLowerCase()]}
|
||||
<Td key={idx} px={4} textStyle='hero-text-small'>
|
||||
<Text>{item[1]}</Text>
|
||||
</Td>
|
||||
);
|
||||
})}
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
import { Box, Flex, Input, InputGroup, Link, Stack, Text, useColorMode } from '@chakra-ui/react';
|
||||
import { FC } from 'react';
|
||||
import { Box, Flex, Link, Stack, Text, useColorMode } from '@chakra-ui/react';
|
||||
import NextLink from 'next/link';
|
||||
|
||||
import { HamburgerIcon, LensIcon, MoonIcon, SunIcon } from '../UI/icons';
|
||||
import { Search } from '../UI'
|
||||
import { DOCS_PAGE, DOWNLOADS_PAGE } from '../../constants';
|
||||
import { MoonIcon, SunIcon } from '../UI/icons';
|
||||
|
||||
import { HeaderButtons } from './';
|
||||
import { MobileMenu } from '../layouts';
|
||||
|
||||
export const Header: FC = () => {
|
||||
const { colorMode, toggleColorMode } = useColorMode();
|
||||
const isDark = colorMode === 'dark';
|
||||
|
||||
return (
|
||||
<Flex mb={4} border='2px solid' borderColor='primary' justifyContent='space-between'>
|
||||
<Flex
|
||||
mb={4}
|
||||
border='2px'
|
||||
borderColor='primary'
|
||||
justifyContent='space-between'
|
||||
position='relative'
|
||||
>
|
||||
<Stack
|
||||
p={4}
|
||||
justifyContent='center'
|
||||
|
@ -27,58 +36,13 @@ export const Header: FC = () => {
|
|||
</Stack>
|
||||
|
||||
<Flex>
|
||||
{/* DOWNLOADS */}
|
||||
<Stack
|
||||
p={4}
|
||||
justifyContent='center'
|
||||
borderRight='2px'
|
||||
borderColor='primary'
|
||||
display={{ base: 'none', md: 'block' }}
|
||||
color='primary'
|
||||
_hover={{
|
||||
textDecoration: 'none',
|
||||
bg: 'primary',
|
||||
color: 'bg !important'
|
||||
}}
|
||||
>
|
||||
<NextLink href={DOWNLOADS_PAGE} passHref>
|
||||
<Link _hover={{ textDecoration: 'none' }}>
|
||||
<Text textStyle='header-font' textTransform='uppercase'>
|
||||
downloads
|
||||
</Text>
|
||||
</Link>
|
||||
</NextLink>
|
||||
</Stack>
|
||||
|
||||
{/* DOCUMENTATION */}
|
||||
<Stack
|
||||
p={4}
|
||||
justifyContent='center'
|
||||
borderRight='2px'
|
||||
borderColor='primary'
|
||||
display={{ base: 'none', md: 'block' }}
|
||||
color='primary'
|
||||
_hover={{
|
||||
textDecoration: 'none',
|
||||
bg: 'primary',
|
||||
color: 'bg !important'
|
||||
}}
|
||||
>
|
||||
<NextLink href={DOCS_PAGE} passHref>
|
||||
<Link _hover={{ textDecoration: 'none' }}>
|
||||
<Text textStyle='header-font' textTransform='uppercase'>
|
||||
documentation
|
||||
</Text>
|
||||
</Link>
|
||||
</NextLink>
|
||||
{/* HEADER BUTTONS */}
|
||||
<Stack display={{ base: 'none', md: 'block' }}>
|
||||
<HeaderButtons />
|
||||
</Stack>
|
||||
|
||||
{/* SEARCH */}
|
||||
<Stack
|
||||
display={{ base: 'none', md: 'block' }}
|
||||
borderRight='2px'
|
||||
borderColor='primary'
|
||||
>
|
||||
<Stack display={{ base: 'none', md: 'block' }}>
|
||||
<Search />
|
||||
</Stack>
|
||||
|
||||
|
@ -96,12 +60,10 @@ export const Header: FC = () => {
|
|||
>
|
||||
{isDark ? <SunIcon color='primary' /> : <MoonIcon color='primary' />}
|
||||
</Box>
|
||||
|
||||
{/* HAMBURGER MENU */}
|
||||
<Box p={4} display={{ base: 'block', md: 'none' }}>
|
||||
<HamburgerIcon color='primary' />
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
{/* MOBILE MENU */}
|
||||
<MobileMenu />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import { FC, MouseEventHandler } from 'react';
|
||||
import { Flex, Link, Stack, Text } from '@chakra-ui/react';
|
||||
import NextLink from 'next/link';
|
||||
|
||||
import { BORDER_WIDTH, DOCS_PAGE, DOWNLOADS_PAGE } from '../../constants';
|
||||
|
||||
interface Props {
|
||||
close?: MouseEventHandler<HTMLAnchorElement>;
|
||||
}
|
||||
|
||||
export const HeaderButtons: FC<Props> = ({ close }) => {
|
||||
const menuItemStyles = {
|
||||
p: { base: 8, md: 4 },
|
||||
borderBottom: { base: BORDER_WIDTH, md: 'none' },
|
||||
borderRight: { base: 'none', md: BORDER_WIDTH },
|
||||
borderColor: { base: 'bg', md: 'primary' },
|
||||
color: { base: 'bg', md: 'primary' },
|
||||
alignItems: 'center',
|
||||
_hover: {
|
||||
textDecoration: 'none',
|
||||
bg: 'primary',
|
||||
color: 'bg !important'
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Flex direction={{ base: 'column', md: 'row' }}>
|
||||
{/* DOWNLOADS */}
|
||||
<NextLink href={DOWNLOADS_PAGE} passHref>
|
||||
<Link _hover={{ textDecoration: 'none' }} onClick={close}>
|
||||
<Stack {...menuItemStyles}>
|
||||
<Text textStyle={{ base: 'header-mobile-button', md: 'header-button' }}>downloads</Text>
|
||||
</Stack>
|
||||
</Link>
|
||||
</NextLink>
|
||||
|
||||
{/* DOCUMENTATION */}
|
||||
<NextLink href={DOCS_PAGE} passHref>
|
||||
<Link _hover={{ textDecoration: 'none' }} onClick={close}>
|
||||
<Stack {...menuItemStyles}>
|
||||
<Text textStyle={{ base: 'header-mobile-button', md: 'header-button' }}>
|
||||
documentation
|
||||
</Text>
|
||||
</Stack>
|
||||
</Link>
|
||||
</NextLink>
|
||||
</Flex>
|
||||
);
|
||||
};
|
|
@ -13,7 +13,7 @@ export const PageMetadata: React.FC<Props> = ({ title, description, image }) =>
|
|||
const router = useRouter();
|
||||
const url = `${SITE_URL}${router.asPath}`;
|
||||
const fullTitle = `${title} | ${SITE_NAME}`;
|
||||
const defaultOgImage = `${SITE_URL}/images/pages/gopher-downloads-front-light.svg`; // TODO: update with right image
|
||||
const defaultOgImage = `${SITE_URL}/images/metadata-gopher.png`;
|
||||
const ogImage = !image ? defaultOgImage : `${SITE_URL}${image}`;
|
||||
|
||||
return (
|
||||
|
@ -43,7 +43,10 @@ export const PageMetadata: React.FC<Props> = ({ title, description, image }) =>
|
|||
<meta name='twitter:description' content={description} />
|
||||
{/* patch to force a cache invalidation of twitter's card bot */}
|
||||
<meta name='twitter:image' content={`${ogImage}/#`} />
|
||||
<link rel='icon' href='/images/favicon.png' />
|
||||
{/* viewport */}
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||
{/* favicon */}
|
||||
<link rel='icon' type='image/x-icon' href='/favicon.ico' />
|
||||
</Head>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
// Libraries
|
||||
import { Code as ChakraCode, Stack, Text, useColorMode } from '@chakra-ui/react';
|
||||
import { nightOwl, prism } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
|
||||
// Constants, utilities
|
||||
import { CLASSNAME_PREFIX } from '../../../constants';
|
||||
import { getProgrammingLanguageName } from '../../../utils';
|
||||
|
||||
// Programming lang syntax highlighters
|
||||
import bash from 'react-syntax-highlighter/dist/cjs/languages/prism/bash';
|
||||
import go from 'react-syntax-highlighter/dist/cjs/languages/prism/go';
|
||||
import graphql from 'react-syntax-highlighter/dist/cjs/languages/prism/graphql';
|
||||
import java from 'react-syntax-highlighter/dist/cjs/languages/prism/java';
|
||||
import javascript from 'react-syntax-highlighter/dist/cjs/languages/prism/javascript';
|
||||
import json from 'react-syntax-highlighter/dist/cjs/languages/prism/json';
|
||||
import python from 'react-syntax-highlighter/dist/cjs/languages/prism/python';
|
||||
import sh from 'react-syntax-highlighter/dist/cjs/languages/prism/shell-session';
|
||||
import solidity from 'react-syntax-highlighter/dist/cjs/languages/prism/solidity';
|
||||
import swift from 'react-syntax-highlighter/dist/cjs/languages/prism/swift';
|
||||
|
||||
// syntax highlighting languages supported
|
||||
SyntaxHighlighter.registerLanguage('bash', bash);
|
||||
SyntaxHighlighter.registerLanguage('terminal', bash);
|
||||
SyntaxHighlighter.registerLanguage('go', go);
|
||||
SyntaxHighlighter.registerLanguage('graphql', graphql);
|
||||
SyntaxHighlighter.registerLanguage('java', java);
|
||||
SyntaxHighlighter.registerLanguage('javascript', javascript);
|
||||
SyntaxHighlighter.registerLanguage('json', json);
|
||||
SyntaxHighlighter.registerLanguage('python', python);
|
||||
SyntaxHighlighter.registerLanguage('sh', sh);
|
||||
SyntaxHighlighter.registerLanguage('solidity', solidity);
|
||||
SyntaxHighlighter.registerLanguage('swift', swift);
|
||||
|
||||
interface Props {
|
||||
className: string;
|
||||
children: string[];
|
||||
inline?: boolean;
|
||||
}
|
||||
export const Code: React.FC<Props> = ({ className, children, inline }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const isDark = colorMode === 'dark';
|
||||
const isTerminal = className?.includes('terminal');
|
||||
const [content] = children;
|
||||
if (inline)
|
||||
return (
|
||||
<Text
|
||||
as='span'
|
||||
px={1}
|
||||
color='primary'
|
||||
bg='code-bg'
|
||||
borderRadius='0.25em'
|
||||
textStyle='inline-code-snippet'
|
||||
>
|
||||
{content}
|
||||
</Text>
|
||||
);
|
||||
if (isTerminal)
|
||||
return (
|
||||
<Stack>
|
||||
<ChakraCode overflow='auto' p={6} background='terminal-bg' color='terminal-text'>
|
||||
{content}
|
||||
</ChakraCode>
|
||||
</Stack>
|
||||
);
|
||||
if (className?.startsWith(CLASSNAME_PREFIX))
|
||||
return (
|
||||
<SyntaxHighlighter
|
||||
language={getProgrammingLanguageName(className)}
|
||||
style={isDark ? nightOwl : prism}
|
||||
customStyle={{ borderRadius: '0.5rem', padding: '1rem' }}
|
||||
>
|
||||
{content}
|
||||
</SyntaxHighlighter>
|
||||
);
|
||||
return <Stack>{content}</Stack>;
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from './Code';
|
|
@ -1,4 +1,4 @@
|
|||
import { Box, Button, Center, Grid, HStack, Image, Link, Stack,Text } from '@chakra-ui/react';
|
||||
import { Box, Button, Center, Grid, HStack, Image, Link, Stack, Text } from '@chakra-ui/react';
|
||||
import { FC } from 'react';
|
||||
import NextLink from 'next/link';
|
||||
|
||||
|
@ -43,7 +43,7 @@ export const DownloadsHero: FC<DownloadsHero> = ({
|
|||
mb={4}
|
||||
templateColumns={{ base: 'repeat(1, 1fr)', md: '1fr 300px', lg: '1fr' }}
|
||||
gap={4}
|
||||
p={4}
|
||||
py={4}
|
||||
>
|
||||
<Stack>
|
||||
<Box as='h1' textStyle='h1'>
|
||||
|
@ -54,11 +54,12 @@ export const DownloadsHero: FC<DownloadsHero> = ({
|
|||
fontFamily='"JetBrains Mono", monospace'
|
||||
lineHeight='21px'
|
||||
mb={{ base: '4 !important', md: '8 !important' }}
|
||||
color='body'
|
||||
>
|
||||
{currentBuild}
|
||||
</Text>
|
||||
|
||||
<Text mb={4}>
|
||||
<Text mb={4} color='body'>
|
||||
You can download the latest 64-bit stable release of Geth for our primary platforms
|
||||
below. Packages for all supported platforms, as well as develop builds, can be found
|
||||
further down the page. If you're looking to install Geth and/or associated tools
|
||||
|
@ -66,20 +67,17 @@ export const DownloadsHero: FC<DownloadsHero> = ({
|
|||
</Text>
|
||||
</Stack>
|
||||
|
||||
<Stack
|
||||
py={{ base: 0 }}
|
||||
px={{ base: 8 }}
|
||||
<Center
|
||||
p={{ base: 0, md: 8 }}
|
||||
flex={{ base: 'none' }}
|
||||
display={{ base: 'block', lg: 'none' }}
|
||||
order={{ base: -1, md: 1 }}
|
||||
>
|
||||
<Center>
|
||||
<GopherDownloads aria-label='Gopher plugged in' w={{ md: 96 }} />
|
||||
</Center>
|
||||
</Stack>
|
||||
<GopherDownloads aria-label='Gopher plugged in' w={{ base: '100%' }} />
|
||||
</Center>
|
||||
</Grid>
|
||||
|
||||
<Grid templateColumns={{ base: 'repeat(1, 1fr)', md: 'repeat(2, 1fr)' }} gap={4} mb={4}>
|
||||
<Grid templateColumns={{ base: 'repeat(1, 1fr)', md: 'repeat(2, 1fr)' }} gap={4}>
|
||||
{Object.keys(DOWNLOAD_HEADER_BUTTONS).map((key: string) => {
|
||||
const { name, buildURL, Svg, ariaLabel } = DOWNLOAD_HEADER_BUTTONS[key];
|
||||
return (
|
||||
|
@ -87,12 +85,10 @@ export const DownloadsHero: FC<DownloadsHero> = ({
|
|||
<Button as='a' variant='downloadsHeader' width={{ base: '100%' }} h={16}>
|
||||
<HStack spacing={4}>
|
||||
<Stack alignItems='center'>
|
||||
<Svg aria-label={ariaLabel} maxH="44px" />
|
||||
<Svg aria-label={ariaLabel} maxH='44px' />
|
||||
</Stack>
|
||||
<Box>
|
||||
<Text textStyle='downloads-button-label'>
|
||||
For {name}
|
||||
</Text>
|
||||
<Text textStyle='downloads-button-label'>For {name}</Text>
|
||||
<Text textStyle='downloads-button-sublabel'>geth {currentBuildVersion}</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
|
@ -102,7 +98,7 @@ export const DownloadsHero: FC<DownloadsHero> = ({
|
|||
})}
|
||||
</Grid>
|
||||
|
||||
<Box textAlign={'center'}>
|
||||
<Box textAlign={'center'} pt={1} pb={2}>
|
||||
<Link href={releaseNotesURL} isExternal variant='light'>
|
||||
Release notes for {currentBuild}
|
||||
</Link>
|
||||
|
|
|
@ -44,7 +44,7 @@ export const DownloadsSection: FC<Props> = ({
|
|||
p={4}
|
||||
borderLeft={{ base: 'none', md: '2px' }}
|
||||
borderTop={{ base: '2px', md: 'none' }}
|
||||
borderColor='primary'
|
||||
borderColor='primary !important'
|
||||
>
|
||||
{sectionDescription}
|
||||
</Center>
|
||||
|
|
|
@ -1,20 +1,43 @@
|
|||
import { Stack, Tabs, TabList, Tab, Text, TabPanel, TabPanels } from '@chakra-ui/react';
|
||||
import { FC } from 'react';
|
||||
|
||||
import { DOWNLOAD_TABS, DOWNLOAD_TAB_COLUMN_HEADERS } from '../../../constants';
|
||||
|
||||
import { DataTable } from '../../UI';
|
||||
|
||||
import { DOWNLOADS_TABLE_TABS, DOWNLOADS_TABLE_TAB_COLUMN_HEADERS } from '../../../constants';
|
||||
import { ReleaseData } from '../../../types';
|
||||
|
||||
interface Props {
|
||||
data: any;
|
||||
linuxData: ReleaseData[];
|
||||
macOSData: ReleaseData[];
|
||||
windowsData: ReleaseData[];
|
||||
iOSData: ReleaseData[];
|
||||
androidData: ReleaseData[];
|
||||
amountOfReleasesToShow: number;
|
||||
setTotalReleases: (idx: number) => void;
|
||||
}
|
||||
|
||||
export const DownloadsTable: FC<Props> = ({ data }) => {
|
||||
export const DownloadsTable: FC<Props> = ({
|
||||
linuxData,
|
||||
macOSData,
|
||||
windowsData,
|
||||
iOSData,
|
||||
androidData,
|
||||
amountOfReleasesToShow,
|
||||
setTotalReleases
|
||||
}) => {
|
||||
const totalReleases = [
|
||||
linuxData.length,
|
||||
macOSData.length,
|
||||
windowsData.length,
|
||||
iOSData.length,
|
||||
androidData.length
|
||||
];
|
||||
|
||||
return (
|
||||
<Stack sx={{ mt: '0 !important' }} borderBottom='2px solid' borderColor='primary'>
|
||||
<Tabs variant='unstyled'>
|
||||
<Tabs variant='unstyled' onChange={idx => setTotalReleases(totalReleases[idx])}>
|
||||
<TabList color='primary' bg='button-bg'>
|
||||
{DOWNLOAD_TABS.map((tab, idx) => {
|
||||
{DOWNLOADS_TABLE_TABS.map((tab, idx) => {
|
||||
return (
|
||||
<Tab
|
||||
key={tab}
|
||||
|
@ -25,7 +48,7 @@ export const DownloadsTable: FC<Props> = ({ data }) => {
|
|||
color: 'bg'
|
||||
}}
|
||||
borderBottom='2px solid'
|
||||
borderRight={idx === DOWNLOAD_TABS.length - 1 ? 'none' : '2px solid'}
|
||||
borderRight={idx === DOWNLOADS_TABLE_TABS.length - 1 ? 'none' : '2px solid'}
|
||||
borderColor='primary'
|
||||
>
|
||||
<Text textStyle='download-tab-label'>{tab}</Text>
|
||||
|
@ -33,21 +56,37 @@ export const DownloadsTable: FC<Props> = ({ data }) => {
|
|||
);
|
||||
})}
|
||||
</TabList>
|
||||
|
||||
<TabPanels>
|
||||
<TabPanel p={0}>
|
||||
<DataTable columnHeaders={DOWNLOAD_TAB_COLUMN_HEADERS} data={data} />
|
||||
<DataTable
|
||||
columnHeaders={DOWNLOADS_TABLE_TAB_COLUMN_HEADERS}
|
||||
data={linuxData.slice(0, amountOfReleasesToShow)}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel p={0}>
|
||||
<DataTable columnHeaders={DOWNLOAD_TAB_COLUMN_HEADERS} data={data} />
|
||||
<DataTable
|
||||
columnHeaders={DOWNLOADS_TABLE_TAB_COLUMN_HEADERS}
|
||||
data={macOSData.slice(0, amountOfReleasesToShow)}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel p={0}>
|
||||
<DataTable columnHeaders={DOWNLOAD_TAB_COLUMN_HEADERS} data={data} />
|
||||
<DataTable
|
||||
columnHeaders={DOWNLOADS_TABLE_TAB_COLUMN_HEADERS}
|
||||
data={windowsData.slice(0, amountOfReleasesToShow)}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel p={0}>
|
||||
<DataTable columnHeaders={DOWNLOAD_TAB_COLUMN_HEADERS} data={data} />
|
||||
<DataTable
|
||||
columnHeaders={DOWNLOADS_TABLE_TAB_COLUMN_HEADERS}
|
||||
data={iOSData.slice(0, amountOfReleasesToShow)}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel p={0}>
|
||||
<DataTable columnHeaders={DOWNLOAD_TAB_COLUMN_HEADERS} data={data} />
|
||||
<DataTable
|
||||
columnHeaders={DOWNLOADS_TABLE_TAB_COLUMN_HEADERS}
|
||||
data={androidData.slice(0, amountOfReleasesToShow)}
|
||||
/>
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Box, Flex, Image, Stack } from '@chakra-ui/react';
|
||||
import { Box, Flex, Grid, GridItem, Image, Stack } from '@chakra-ui/react';
|
||||
import { FC } from 'react';
|
||||
import { GopherHomeLinks } from '../svgs';
|
||||
|
||||
|
@ -8,36 +8,33 @@ interface Props {
|
|||
|
||||
export const SpecificVersionsSection: FC<Props> = ({ children }) => {
|
||||
return (
|
||||
<Flex
|
||||
id='specificversions'
|
||||
border='2px'
|
||||
borderColor='primary'
|
||||
flexDir={{ base: 'column', md: 'row' }}
|
||||
>
|
||||
<Flex
|
||||
p={4}
|
||||
alignItems='center'
|
||||
justifyContent='center'
|
||||
borderBottom={{ base: '2px', md: 'none' }}
|
||||
borderRight={{ base: 'none', md: '2px' }}
|
||||
borderColor='primary'
|
||||
flex='none'
|
||||
>
|
||||
<GopherHomeLinks />
|
||||
</Flex>
|
||||
<Flex flexDir='column'>
|
||||
<Stack
|
||||
p={4}
|
||||
borderBottom='2px'
|
||||
borderColor='primary'
|
||||
sx={{ mt: '0 !important' }}
|
||||
>
|
||||
<Box as='h2' textStyle='h2'>
|
||||
Specific Versions
|
||||
</Box>
|
||||
</Stack>
|
||||
{children}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Grid id='specificversions' templateColumns={{ base: '1fr', md: '300px 1fr' }} gap={4}>
|
||||
<GridItem w='auto'>
|
||||
<Box h='100%'>
|
||||
{/* TODO: replace with animated/video version */}
|
||||
<Stack
|
||||
justifyContent='center'
|
||||
alignItems='center'
|
||||
p={4}
|
||||
border='2px solid'
|
||||
borderColor='primary'
|
||||
h='100%'
|
||||
>
|
||||
<GopherHomeLinks />
|
||||
</Stack>
|
||||
</Box>
|
||||
</GridItem>
|
||||
|
||||
<GridItem>
|
||||
<Flex flexDir='column' border='2px solid' borderColor='primary' pb={6}>
|
||||
<Stack p={4} borderBottom='2px' borderColor='primary' sx={{ mt: '0 !important' }}>
|
||||
<Box as='h2' textStyle='h2'>
|
||||
Specific Versions
|
||||
</Box>
|
||||
</Stack>
|
||||
{children}
|
||||
</Flex>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,9 +19,9 @@ export const HomeHero: FC = () => {
|
|||
textStyle='h1'
|
||||
mb={{ base: 2, md: 4 }}
|
||||
textAlign={{ base: 'center', md: 'left' }}
|
||||
fontSize={{ base: '5xl', md: '8xl' }}
|
||||
lineHeight={{ md: '6rem' }}
|
||||
fontWeight='500'
|
||||
fontSize={{ base: '2.75rem', md: '8xl' }}
|
||||
lineHeight={{ base: '3.375rem', md: '6rem' }}
|
||||
fontWeight={{ base: 700, md: 500 }}
|
||||
>
|
||||
go-ethereum
|
||||
</Box>
|
||||
|
@ -54,7 +54,7 @@ export const HomeHero: FC = () => {
|
|||
</Button>
|
||||
</NextLink>
|
||||
|
||||
<Text mt={1} fontSize='13px' fontFamily='"Inter", sans-serif' alignSelf='center'>
|
||||
<Text mt={1} textStyle='hero-text-small'>
|
||||
Read our documentation
|
||||
</Text>
|
||||
</Flex>
|
||||
|
|
|
@ -18,11 +18,7 @@ export const QuickLinks: FC = () => {
|
|||
sx={{ mt: '0 !important' }}
|
||||
>
|
||||
{/* get started */}
|
||||
<GridItem
|
||||
borderRight='2px solid'
|
||||
borderBottom='2px solid'
|
||||
borderColor='primary'
|
||||
>
|
||||
<GridItem borderRight='2px solid' borderBottom='2px solid' borderColor='primary'>
|
||||
<Stack p={4} h='100%'>
|
||||
<Text textStyle='quick-link-text' mb={-1}>
|
||||
Don't know where to start?
|
||||
|
@ -60,11 +56,7 @@ export const QuickLinks: FC = () => {
|
|||
</GridItem>
|
||||
|
||||
{/* faq */}
|
||||
<GridItem
|
||||
borderRight='2px solid'
|
||||
borderBottom='2px solid'
|
||||
borderColor='primary'
|
||||
>
|
||||
<GridItem borderRight='2px solid' borderBottom='2px solid' borderColor='primary'>
|
||||
<Stack p={4} h='100%'>
|
||||
<Text textStyle='quick-link-text' mb={-1}>
|
||||
Have doubts?
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Box, Grid, GridItem, Stack } from '@chakra-ui/react';
|
||||
import { FC } from 'react';
|
||||
|
||||
import { ButtonLinkSecondary } from '..'
|
||||
import { ButtonLinkSecondary } from '..';
|
||||
import { GopherHomeNodes } from '../svgs/GopherHomeNodes';
|
||||
import { ETHEREUM_ORG_RUN_A_NODE_URL } from '../../../constants';
|
||||
|
||||
|
|
|
@ -4,8 +4,11 @@ export const DiscordIcon = createIcon({
|
|||
displayName: 'DiscordIcon',
|
||||
viewBox: '0 0 32 24',
|
||||
path: (
|
||||
<svg width="32" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M26.9846 2.02697C26.9758 2.01 26.9612 1.99671 26.9435 1.98947C24.8961 1.05243 22.7354 0.384243 20.5157 0.00163895C20.4955 -0.00210093 20.4747 0.000597065 20.4561 0.00934923C20.4376 0.0181014 20.4223 0.0324621 20.4124 0.0503891C20.1182 0.583045 19.8511 1.13017 19.6122 1.68968C17.2194 1.32737 14.7855 1.32737 12.3927 1.68968C12.1522 1.12875 11.8808 0.581488 11.5799 0.0503891C11.5696 0.0328517 11.5542 0.0188217 11.5357 0.0101264C11.5173 0.0014311 11.4967 -0.0015265 11.4765 0.00163895C9.25655 0.38344 7.09577 1.05167 5.0486 1.98952C5.03107 1.99693 5.01629 2.00958 5.00628 2.02573C0.912331 8.12422 -0.209155 14.0728 0.341008 19.9476C0.342556 19.962 0.346991 19.976 0.354049 19.9886C0.361107 20.0013 0.370644 20.0124 0.382093 20.0213C2.76596 21.7819 5.43234 23.1259 8.26746 23.9957C8.28743 24.0017 8.30875 24.0014 8.32855 23.9949C8.34836 23.9885 8.36571 23.9761 8.37825 23.9595C8.98718 23.133 9.52673 22.2579 9.99142 21.3429C9.9978 21.3304 10.0014 21.3166 10.0021 21.3026C10.0028 21.2885 10.0005 21.2745 9.99528 21.2614C9.99011 21.2483 9.98221 21.2364 9.97212 21.2266C9.96202 21.2167 9.94994 21.2091 9.93669 21.2043C9.08586 20.8796 8.26216 20.4881 7.47331 20.0336C7.45898 20.0252 7.44695 20.0134 7.43827 19.9993C7.42959 19.9851 7.42454 19.9691 7.42356 19.9525C7.42257 19.936 7.42569 19.9194 7.43264 19.9044C7.43958 19.8893 7.45014 19.8762 7.46338 19.8661C7.6289 19.7424 7.79453 19.6138 7.95258 19.4838C7.96662 19.4723 7.98362 19.4649 8.00164 19.4624C8.01967 19.46 8.03802 19.4627 8.05462 19.4701C13.2227 21.8228 18.8178 21.8228 23.9247 19.4701C23.9414 19.4622 23.9599 19.4592 23.9782 19.4614C23.9965 19.4636 24.0138 19.4709 24.028 19.4826C24.1861 19.6125 24.3517 19.7424 24.5185 19.8661C24.5318 19.8761 24.5424 19.8891 24.5495 19.9041C24.5565 19.9191 24.5598 19.9356 24.5589 19.9522C24.5581 19.9687 24.5531 19.9848 24.5446 19.999C24.536 20.0132 24.524 20.0251 24.5098 20.0336C23.7227 20.4919 22.8983 20.8832 22.0452 21.2031C22.032 21.2081 22.0199 21.2159 22.0099 21.2259C21.9999 21.2358 21.9921 21.2478 21.987 21.261C21.9819 21.2742 21.9797 21.2884 21.9805 21.3025C21.9813 21.3166 21.985 21.3304 21.9915 21.3429C22.464 22.2528 23.0027 23.1268 23.6034 23.958C23.6156 23.9751 23.6329 23.9879 23.6528 23.9946C23.6727 24.0014 23.6942 24.0017 23.7142 23.9955C26.5544 23.1287 29.2255 21.7846 31.6123 20.0213C31.624 20.0128 31.6336 20.002 31.6407 19.9895C31.6478 19.977 31.6521 19.9632 31.6534 19.9489C32.3121 13.1569 30.5507 7.25711 26.9846 2.02697ZM10.7632 16.3704C9.20726 16.3704 7.92519 14.9461 7.92519 13.1969C7.92519 11.4477 9.18239 10.0233 10.7632 10.0233C12.3564 10.0233 13.6261 11.4601 13.6012 13.1968C13.6012 14.9461 12.344 16.3704 10.7632 16.3704ZM21.2563 16.3704C19.7004 16.3704 18.4183 14.9461 18.4183 13.1969C18.4183 11.4477 19.6755 10.0233 21.2563 10.0233C22.8496 10.0233 24.1192 11.4601 24.0943 13.1968C24.0943 14.9461 22.8496 16.3704 21.2563 16.3704Z" fill="currentColor"/>
|
||||
<svg width='32' height='24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M26.9846 2.02697C26.9758 2.01 26.9612 1.99671 26.9435 1.98947C24.8961 1.05243 22.7354 0.384243 20.5157 0.00163895C20.4955 -0.00210093 20.4747 0.000597065 20.4561 0.00934923C20.4376 0.0181014 20.4223 0.0324621 20.4124 0.0503891C20.1182 0.583045 19.8511 1.13017 19.6122 1.68968C17.2194 1.32737 14.7855 1.32737 12.3927 1.68968C12.1522 1.12875 11.8808 0.581488 11.5799 0.0503891C11.5696 0.0328517 11.5542 0.0188217 11.5357 0.0101264C11.5173 0.0014311 11.4967 -0.0015265 11.4765 0.00163895C9.25655 0.38344 7.09577 1.05167 5.0486 1.98952C5.03107 1.99693 5.01629 2.00958 5.00628 2.02573C0.912331 8.12422 -0.209155 14.0728 0.341008 19.9476C0.342556 19.962 0.346991 19.976 0.354049 19.9886C0.361107 20.0013 0.370644 20.0124 0.382093 20.0213C2.76596 21.7819 5.43234 23.1259 8.26746 23.9957C8.28743 24.0017 8.30875 24.0014 8.32855 23.9949C8.34836 23.9885 8.36571 23.9761 8.37825 23.9595C8.98718 23.133 9.52673 22.2579 9.99142 21.3429C9.9978 21.3304 10.0014 21.3166 10.0021 21.3026C10.0028 21.2885 10.0005 21.2745 9.99528 21.2614C9.99011 21.2483 9.98221 21.2364 9.97212 21.2266C9.96202 21.2167 9.94994 21.2091 9.93669 21.2043C9.08586 20.8796 8.26216 20.4881 7.47331 20.0336C7.45898 20.0252 7.44695 20.0134 7.43827 19.9993C7.42959 19.9851 7.42454 19.9691 7.42356 19.9525C7.42257 19.936 7.42569 19.9194 7.43264 19.9044C7.43958 19.8893 7.45014 19.8762 7.46338 19.8661C7.6289 19.7424 7.79453 19.6138 7.95258 19.4838C7.96662 19.4723 7.98362 19.4649 8.00164 19.4624C8.01967 19.46 8.03802 19.4627 8.05462 19.4701C13.2227 21.8228 18.8178 21.8228 23.9247 19.4701C23.9414 19.4622 23.9599 19.4592 23.9782 19.4614C23.9965 19.4636 24.0138 19.4709 24.028 19.4826C24.1861 19.6125 24.3517 19.7424 24.5185 19.8661C24.5318 19.8761 24.5424 19.8891 24.5495 19.9041C24.5565 19.9191 24.5598 19.9356 24.5589 19.9522C24.5581 19.9687 24.5531 19.9848 24.5446 19.999C24.536 20.0132 24.524 20.0251 24.5098 20.0336C23.7227 20.4919 22.8983 20.8832 22.0452 21.2031C22.032 21.2081 22.0199 21.2159 22.0099 21.2259C21.9999 21.2358 21.9921 21.2478 21.987 21.261C21.9819 21.2742 21.9797 21.2884 21.9805 21.3025C21.9813 21.3166 21.985 21.3304 21.9915 21.3429C22.464 22.2528 23.0027 23.1268 23.6034 23.958C23.6156 23.9751 23.6329 23.9879 23.6528 23.9946C23.6727 24.0014 23.6942 24.0017 23.7142 23.9955C26.5544 23.1287 29.2255 21.7846 31.6123 20.0213C31.624 20.0128 31.6336 20.002 31.6407 19.9895C31.6478 19.977 31.6521 19.9632 31.6534 19.9489C32.3121 13.1569 30.5507 7.25711 26.9846 2.02697ZM10.7632 16.3704C9.20726 16.3704 7.92519 14.9461 7.92519 13.1969C7.92519 11.4477 9.18239 10.0233 10.7632 10.0233C12.3564 10.0233 13.6261 11.4601 13.6012 13.1968C13.6012 14.9461 12.344 16.3704 10.7632 16.3704ZM21.2563 16.3704C19.7004 16.3704 18.4183 14.9461 18.4183 13.1969C18.4183 11.4477 19.6755 10.0233 21.2563 10.0233C22.8496 10.0233 24.1192 11.4601 24.0943 13.1968C24.0943 14.9461 22.8496 16.3704 21.2563 16.3704Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
});
|
||||
|
|
|
@ -4,8 +4,11 @@ export const GitHubIcon = createIcon({
|
|||
displayName: 'GitHubIcon',
|
||||
viewBox: '0 0 26 24',
|
||||
path: (
|
||||
<svg width="26" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.82878 19.3248C8.82878 19.424 8.71193 19.5034 8.56459 19.5034C8.39693 19.5183 8.28007 19.4389 8.28007 19.3248C8.28007 19.2255 8.39693 19.1461 8.54427 19.1461C8.69669 19.1312 8.82878 19.2106 8.82878 19.3248ZM7.2487 19.1014C7.21314 19.2007 7.31475 19.3148 7.46717 19.3446C7.59927 19.3942 7.75169 19.3446 7.78217 19.2454C7.81265 19.1461 7.71612 19.032 7.5637 18.9873C7.43161 18.9526 7.28427 19.0022 7.2487 19.1014ZM9.49435 19.0171C9.34701 19.0518 9.2454 19.1461 9.26064 19.2603C9.27588 19.3595 9.40798 19.424 9.5604 19.3893C9.70774 19.3545 9.80935 19.2603 9.79411 19.161C9.77886 19.0667 9.64169 19.0022 9.49435 19.0171ZM12.8374 0C5.79056 0 0.399994 5.22573 0.399994 12.109C0.399994 17.6126 3.94628 22.3222 9.01169 23.9798C9.66201 24.0939 9.89064 23.7019 9.89064 23.3793C9.89064 23.0716 9.8754 21.3744 9.8754 20.3322C9.8754 20.3322 6.31895 21.0766 5.57209 18.8533C5.57209 18.8533 4.9929 17.4092 4.15967 17.037C4.15967 17.037 2.9962 16.2578 4.24096 16.2727C4.24096 16.2727 5.50604 16.372 6.20209 17.5531C7.31475 19.4687 9.17935 18.9178 9.90588 18.5903C10.0227 17.7963 10.353 17.2454 10.7188 16.9179C7.8787 16.6102 5.01322 16.2082 5.01322 11.4341C5.01322 10.0693 5.39935 9.38447 6.21225 8.51103C6.08015 8.18846 5.6483 6.85846 6.34435 5.14136C7.4062 4.81878 9.84999 6.48129 9.84999 6.48129C10.8661 6.20338 11.9585 6.05946 13.0406 6.05946C14.1228 6.05946 15.2152 6.20338 16.2313 6.48129C16.2313 6.48129 18.6751 4.81382 19.7369 5.14136C20.433 6.86342 20.0011 8.18846 19.869 8.51103C20.6819 9.38943 21.1798 10.0743 21.1798 11.4341C21.1798 16.2231 18.1873 16.6052 15.3473 16.9179C15.8147 17.3099 16.211 18.0543 16.211 19.2205C16.211 20.893 16.1957 22.9624 16.1957 23.3694C16.1957 23.6919 16.4294 24.084 17.0747 23.9699C22.1553 22.3222 25.6 17.6126 25.6 12.109C25.6 5.22573 19.8843 0 12.8374 0ZM5.33838 17.1164C5.27233 17.166 5.28757 17.2801 5.37395 17.3744C5.45524 17.4538 5.57209 17.4886 5.63814 17.424C5.70419 17.3744 5.68895 17.2603 5.60257 17.166C5.52128 17.0866 5.40443 17.0518 5.33838 17.1164ZM4.78967 16.7144C4.75411 16.7789 4.80491 16.8583 4.90653 16.9079C4.98782 16.9576 5.08943 16.9427 5.12499 16.8732C5.16056 16.8087 5.10975 16.7293 5.00814 16.6796C4.90653 16.6499 4.82524 16.6648 4.78967 16.7144ZM6.4358 18.4811C6.35451 18.5456 6.38499 18.6945 6.50185 18.7888C6.6187 18.9029 6.76604 18.9178 6.83209 18.8384C6.89814 18.7739 6.86765 18.625 6.76604 18.5307C6.65427 18.4166 6.50185 18.4017 6.4358 18.4811ZM5.85661 17.7516C5.77532 17.8012 5.77532 17.9302 5.85661 18.0444C5.9379 18.1585 6.07507 18.2082 6.14112 18.1585C6.22241 18.094 6.22241 17.965 6.14112 17.8508C6.06999 17.7367 5.9379 17.6871 5.85661 17.7516Z" fill="currentColor"/>
|
||||
<svg width='26' height='24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M8.82878 19.3248C8.82878 19.424 8.71193 19.5034 8.56459 19.5034C8.39693 19.5183 8.28007 19.4389 8.28007 19.3248C8.28007 19.2255 8.39693 19.1461 8.54427 19.1461C8.69669 19.1312 8.82878 19.2106 8.82878 19.3248ZM7.2487 19.1014C7.21314 19.2007 7.31475 19.3148 7.46717 19.3446C7.59927 19.3942 7.75169 19.3446 7.78217 19.2454C7.81265 19.1461 7.71612 19.032 7.5637 18.9873C7.43161 18.9526 7.28427 19.0022 7.2487 19.1014ZM9.49435 19.0171C9.34701 19.0518 9.2454 19.1461 9.26064 19.2603C9.27588 19.3595 9.40798 19.424 9.5604 19.3893C9.70774 19.3545 9.80935 19.2603 9.79411 19.161C9.77886 19.0667 9.64169 19.0022 9.49435 19.0171ZM12.8374 0C5.79056 0 0.399994 5.22573 0.399994 12.109C0.399994 17.6126 3.94628 22.3222 9.01169 23.9798C9.66201 24.0939 9.89064 23.7019 9.89064 23.3793C9.89064 23.0716 9.8754 21.3744 9.8754 20.3322C9.8754 20.3322 6.31895 21.0766 5.57209 18.8533C5.57209 18.8533 4.9929 17.4092 4.15967 17.037C4.15967 17.037 2.9962 16.2578 4.24096 16.2727C4.24096 16.2727 5.50604 16.372 6.20209 17.5531C7.31475 19.4687 9.17935 18.9178 9.90588 18.5903C10.0227 17.7963 10.353 17.2454 10.7188 16.9179C7.8787 16.6102 5.01322 16.2082 5.01322 11.4341C5.01322 10.0693 5.39935 9.38447 6.21225 8.51103C6.08015 8.18846 5.6483 6.85846 6.34435 5.14136C7.4062 4.81878 9.84999 6.48129 9.84999 6.48129C10.8661 6.20338 11.9585 6.05946 13.0406 6.05946C14.1228 6.05946 15.2152 6.20338 16.2313 6.48129C16.2313 6.48129 18.6751 4.81382 19.7369 5.14136C20.433 6.86342 20.0011 8.18846 19.869 8.51103C20.6819 9.38943 21.1798 10.0743 21.1798 11.4341C21.1798 16.2231 18.1873 16.6052 15.3473 16.9179C15.8147 17.3099 16.211 18.0543 16.211 19.2205C16.211 20.893 16.1957 22.9624 16.1957 23.3694C16.1957 23.6919 16.4294 24.084 17.0747 23.9699C22.1553 22.3222 25.6 17.6126 25.6 12.109C25.6 5.22573 19.8843 0 12.8374 0ZM5.33838 17.1164C5.27233 17.166 5.28757 17.2801 5.37395 17.3744C5.45524 17.4538 5.57209 17.4886 5.63814 17.424C5.70419 17.3744 5.68895 17.2603 5.60257 17.166C5.52128 17.0866 5.40443 17.0518 5.33838 17.1164ZM4.78967 16.7144C4.75411 16.7789 4.80491 16.8583 4.90653 16.9079C4.98782 16.9576 5.08943 16.9427 5.12499 16.8732C5.16056 16.8087 5.10975 16.7293 5.00814 16.6796C4.90653 16.6499 4.82524 16.6648 4.78967 16.7144ZM6.4358 18.4811C6.35451 18.5456 6.38499 18.6945 6.50185 18.7888C6.6187 18.9029 6.76604 18.9178 6.83209 18.8384C6.89814 18.7739 6.86765 18.625 6.76604 18.5307C6.65427 18.4166 6.50185 18.4017 6.4358 18.4811ZM5.85661 17.7516C5.77532 17.8012 5.77532 17.9302 5.85661 18.0444C5.9379 18.1585 6.07507 18.2082 6.14112 18.1585C6.22241 18.094 6.22241 17.965 6.14112 17.8508C6.06999 17.7367 5.9379 17.6871 5.85661 17.7516Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
});
|
||||
|
|
|
@ -4,16 +4,31 @@ export const SunIcon = createIcon({
|
|||
displayName: 'SunIcon',
|
||||
viewBox: '0 0 44 44',
|
||||
path: (
|
||||
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21 0H23V12H21V0Z" fill="currentColor"/>
|
||||
<path d="M0 23V21H12V23H0Z" fill="currentColor"/>
|
||||
<path d="M44 21H32V23H44V21Z" fill="currentColor"/>
|
||||
<path d="M21 32H23V44H21V32Z" fill="currentColor"/>
|
||||
<path d="M7.15074 5.73633L5.73653 7.15054L14.2218 15.6358L15.636 14.2216L7.15074 5.73633Z" fill="currentColor"/>
|
||||
<path d="M36.8493 5.73618L38.2635 7.15039L29.7782 15.6357L28.364 14.2215L36.8493 5.73618Z" fill="currentColor"/>
|
||||
<path d="M29.7782 28.3643L28.364 29.7785L36.8492 38.2638L38.2635 36.8495L29.7782 28.3643Z" fill="currentColor"/>
|
||||
<path d="M14.2218 28.3641L15.636 29.7783L7.15076 38.2636L5.73655 36.8494L14.2218 28.3641Z" fill="currentColor"/>
|
||||
<path d="M30 22C30 26.4183 26.4183 30 22 30C17.5817 30 14 26.4183 14 22C14 17.5817 17.5817 14 22 14C26.4183 14 30 17.5817 30 22Z" fill="currentColor"/>
|
||||
<svg width='44' height='44' viewBox='0 0 44 44' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path d='M21 0H23V12H21V0Z' fill='currentColor' />
|
||||
<path d='M0 23V21H12V23H0Z' fill='currentColor' />
|
||||
<path d='M44 21H32V23H44V21Z' fill='currentColor' />
|
||||
<path d='M21 32H23V44H21V32Z' fill='currentColor' />
|
||||
<path
|
||||
d='M7.15074 5.73633L5.73653 7.15054L14.2218 15.6358L15.636 14.2216L7.15074 5.73633Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M36.8493 5.73618L38.2635 7.15039L29.7782 15.6357L28.364 14.2215L36.8493 5.73618Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M29.7782 28.3643L28.364 29.7785L36.8492 38.2638L38.2635 36.8495L29.7782 28.3643Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M14.2218 28.3641L15.636 29.7783L7.15076 38.2636L5.73655 36.8494L14.2218 28.3641Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M30 22C30 26.4183 26.4183 30 22 30C17.5817 30 14 26.4183 14 22C14 17.5817 17.5817 14 22 14C26.4183 14 30 17.5817 30 22Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export * from './ButtonLinkSecondary';
|
||||
export * from './DataTable';
|
||||
export * from './Header';
|
||||
export * from './HeaderButtons';
|
||||
export * from './PageMetadata';
|
||||
export * from './Search';
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import { FC } from 'react';
|
||||
import { Input, InputGroup, Stack } from '@chakra-ui/react';
|
||||
|
||||
import { BORDER_WIDTH } from '../../../constants';
|
||||
import { LensIcon } from '../icons';
|
||||
|
||||
export const Search: FC = () => {
|
||||
return (
|
||||
<Stack
|
||||
borderBottom={{ base: BORDER_WIDTH, md: 'none' }}
|
||||
borderRight={{ base: 'none', md: BORDER_WIDTH }}
|
||||
borderColor={{ base: 'bg', md: 'primary' }}
|
||||
px={4}
|
||||
py={{ base: 8, md: 4 }}
|
||||
_hover={{ base: { bg: 'primary' }, md: { bg: 'none' } }}
|
||||
>
|
||||
<InputGroup>
|
||||
<Input
|
||||
variant='unstyled'
|
||||
placeholder='search'
|
||||
size='md'
|
||||
_placeholder={{ color: { base: 'bg', md: 'primary' }, fontStyle: 'italic' }}
|
||||
/>
|
||||
<Stack pl={4} justifyContent='center' alignItems='center'>
|
||||
<LensIcon color={{ base: 'bg', md: 'primary' }} fontSize={{ base: '3xl', md: 'md' }} />
|
||||
</Stack>
|
||||
</InputGroup>
|
||||
</Stack>
|
||||
);
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from './Search';
|
|
@ -7,15 +7,47 @@ const Icon = createIcon({
|
|||
displayName: 'GlyphHome',
|
||||
viewBox: `0 0 ${w} ${h}`,
|
||||
path: (
|
||||
<svg width={w} height={h} fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M90.0002 276.5V207.379L2.76453 157.376L90.0002 276.5Z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round"/>
|
||||
<path d="M90.0001 276.5V207.379L177.236 157.376L90.0001 276.5Z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round"/>
|
||||
<path d="M89.9999 190.325V102.883L1.5 141.27L89.9999 190.325Z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round"/>
|
||||
<path d="M90.0001 190.325V102.883L178.5 141.27L90.0001 190.325Z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round"/>
|
||||
<path d="M1.5 140.901L89.9999 1.5V102.26L1.5 140.901Z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round"/>
|
||||
<path d="M178.5 140.901L90.0001 1.5V102.26L178.5 140.901Z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round"/>
|
||||
<svg width={w} height={h} fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M90.0002 276.5V207.379L2.76453 157.376L90.0002 276.5Z'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M90.0001 276.5V207.379L177.236 157.376L90.0001 276.5Z'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M89.9999 190.325V102.883L1.5 141.27L89.9999 190.325Z'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M90.0001 190.325V102.883L178.5 141.27L90.0001 190.325Z'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M1.5 140.901L89.9999 1.5V102.26L1.5 140.901Z'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M178.5 140.901L90.0001 1.5V102.26L178.5 140.901Z'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
});
|
||||
|
||||
export const GlyphHome: React.FC<IconProps> = (props) => <Icon h={h} w={w} color='primary' {...props} />;
|
||||
export const GlyphHome: React.FC<IconProps> = props => (
|
||||
<Icon h={h} w={w} color='primary' {...props} />
|
||||
);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
|||
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from '@chakra-ui/react';
|
||||
import NextLink from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import { FC } from 'react';
|
||||
|
||||
export const Breadcrumbs: FC = () => {
|
||||
const router = useRouter();
|
||||
|
||||
let pathSplit = router.asPath.split('/');
|
||||
pathSplit = pathSplit.splice(1, pathSplit.length);
|
||||
|
||||
return (
|
||||
<Breadcrumb>
|
||||
{pathSplit.map((path: string, idx: number) => {
|
||||
return (
|
||||
<BreadcrumbItem key={path}>
|
||||
<NextLink href={`/${pathSplit.slice(0, idx + 1).join('/')}`} passHref>
|
||||
<BreadcrumbLink color={idx + 1 === pathSplit.length ? 'body' : 'primary'}>
|
||||
{path}
|
||||
</BreadcrumbLink>
|
||||
</NextLink>
|
||||
</BreadcrumbItem>
|
||||
);
|
||||
})}
|
||||
</Breadcrumb>
|
||||
);
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from './Breadcrumbs';
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue