Compare commits

..

770 Commits

Author SHA1 Message Date
Felix Lange
c3d9ca62c1 all: release go-ethereum v1.13.7 2023-12-19 13:30:06 +01:00
Felix Lange
3fd568855f params: go-ethereum v1.13.7 stable 2023-12-19 13:25:03 +01:00
dependabot[bot]
0cc192bd3a build(deps): bump golang.org/x/crypto from 0.15.0 to 0.17.0 (#28702)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.15.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.15.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-19 10:50:02 +01:00
Martin HS
435bed5da0 ci: disable lint on travis (#28706) 2023-12-19 10:35:02 +01:00
Martin HS
5a9dda64ce .travis: set lower GOGC value (#28705)
As documented on https://golangci-lint.run/usage/performance/ , a lower
GOGC value causes less peak mem consumption when running the linter.

Exceeding 3Gb is a common cause for build failures, according to
https://docs.travis-ci.com/user/common-build-problems/#my-build-script-is-killed-without-any-error
2023-12-19 09:24:23 +01:00
Martin HS
952b343cb3 build: make linter emit output (#28704) 2023-12-19 08:55:04 +01:00
wangyifan
cd58897f18 core/rawdb: implement size reporting for live items in freezer_table (#28525)
This is the fix to issue #27483. A new hiddenBytes() is introduced to calculate the byte size of hidden items in the freezer table. When reporting the size of the freezer table, size of the hidden items will be subtracted from the total size.

---------

Co-authored-by: Yifan <Yifan Wang>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-12-18 20:10:54 +01:00
Delweng
54a400ee71 internal/ethapi: ethSendTransaction check baseFee (#27834)
If the EIP-1559 is activated, reject 0-priced transactions in the rpc level
2023-12-18 20:09:41 +01:00
Felix Lange
4410c1416a params: begin v1.13.7 release cycle 2023-12-18 19:10:11 +01:00
Felix Lange
da6cdaf635 all: release go-ethereum v1.13.6 2023-12-18 19:06:41 +01:00
Felix Lange
5ba3d578ee Merge branch 'release/1.13' into release-1.13.6 2023-12-18 18:55:38 +01:00
Felix Lange
a18b845ecd params: release go-ethereum v1.13.6 stable 2023-12-18 18:53:47 +01:00
Delweng
c18c5c3d92 cmd/evm: t8n support custom tracers (#28557)
This change implements ability for the `evm t8n` tool to use custom tracers; either 'native' golang tracers or javascript tracers.
2023-12-18 15:16:25 +01:00
Martin HS
553bafc127 cmd/evm, cmd/clef, cmd/bootnode: fix / unify logging (#28696)
This change fixes a problem with our non-core binaries: evm, clef, bootnode.

First of all, they failed to convert from legacy loglevels 1 to 5, to the new slog loglevels -4 to 4.

Secondly, the logging was actually setup in the init phase, and then overridden in the main. This is not needed for evm, since it used the same flag name as the main geth verbosity. Better to let the flags/internal handle the logging init.
2023-12-18 14:11:27 +01:00
jwasinger
05bbc56677 cmd/evm: default to mirror mainnet forks enabled (#28691)
cmd/evm:  default to using dev chain config (all mainnet HFs activated at block/timestamp 0
2023-12-18 13:56:27 +01:00
Sebastian Stammler
02766d349a internal/flags: add missing flag types for auto-env-var generation (#28692)
Certain flags, such as `--rpc.txfeecap` currently do not have an env-var auto-generated for them. This change adds three missing cli flag types to the auto env-var helper function to fix this.
2023-12-18 13:28:41 +01:00
Felix Lange
5b22a472d6 p2p/discover: add liveness check in collectTableNodes (#28686)
* p2p/discover: add liveness check in collectTableNodes

* p2p/discover: fix test

* p2p/discover: rename to appendLiveNodes

* p2p/discover: add dedup logic back

* p2p/discover: simplify

* p2p/discover: fix issue found by test
2023-12-18 10:47:21 +01:00
alex
edc864f9ba all: fix typos in comments (#28682)
chore(core,eth):fix a couple of typos
2023-12-18 09:35:12 +01:00
FletcherMan
f1794ba278 miner: eliminate the dead loop possibility for newWorkLoop and mainLoop (#28677)
discard the intervalAdjust message if the channel is full
2023-12-15 11:48:55 +08:00
Elias Rad
0f74aad641 all: fix typos in comments (#28662)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-12-13 23:33:46 +01:00
Ursulafe
b2ced97ac4 eth/fetcher, eth/gasestimator: fix typos in comments (#28675) 2023-12-13 23:32:17 +01:00
ucwong
81fd1b3cf9 core/txpool : small cleanup refactors (#28654) 2023-12-12 17:23:36 +02:00
Ford
17c2b3c194 eth/protocols/eth: fix typos in comments (#28652) 2023-12-12 14:47:59 +01:00
Ng Wei Han
a3ca1b2818 cmd/utils: fix HTTPHost, WSHost flag priority (#28669)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-12-12 14:40:50 +01:00
rjl493456442
e206d3f897 trie: remove inconsistent trie nodes during sync in path mode (#28595)
This fixes a database corruption issue that could occur during state healing.
When sync is aborted while certain modifications were already committed, and a
reorg occurs, the database would contain incorrect trie nodes stored by path.
These nodes need to detected/deleted in order to obtain a complete and fully correct state
after state healing.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-12-08 14:28:23 +01:00
Péter Szilágyi
d98d70f670 cmd/utils, eth: disallow invalid snap sync / snapshot flag combos (#28657)
* eth: prevent startup in snap mode without snapshots

* cmd/utils: try to fix bad flag combos wrt snap sync and snapshot generation
2023-12-08 15:16:04 +02:00
Felföldi Zsolt
fff843cfaf beacon/light: add CommitteeChain (#27766)
This change implements CommitteeChain which is a key component of the beacon light client. It is a passive data structure that can validate, hold and update a chain of beacon light sync committees and updates, starting from a checkpoint that proves the starting committee through a beacon block hash, header and corresponding state. Once synced to the current sync period, CommitteeChain can also validate signed beacon headers.
2023-12-08 13:38:00 +01:00
Martin HS
1048e2d6a3 cmd/evm: fix dump after state-test exec (#28650)
The dump after state-test didn't work, the problem was an error, "Already committed", which was silently ignored. 

This change re-initialises the state, so the dumping works again.
2023-12-08 11:06:01 +01:00
Martin HS
5a45e7a631 rpc: fix ns/µs mismatch in metrics (#28649)
The rpc/duration/all meter was in nanoseconds, the individual meter in microseconds.
This PR changes it so both of them use nanoseconds.
2023-12-08 09:40:50 +01:00
Marius Kjærstad
77c4bbcaa5 build: upgrade -dlgo version to Go 1.21.5 (#28648) 2023-12-07 12:45:09 +02:00
Guillaume Ballet
a113497dd7 tests/fuzzers/bls12381: deactivate BLS fuzzer when CGO_ENABLED=0 (#28653)
tests/fuzzers/bls12381: deactivate fuzzer when CGO_ENABLED=0
2023-12-07 10:07:20 +01:00
Marius van der Wijden
55b483d82a ethdb/pebble: remove a dependency (#28627)
The dependency was not really used anyway, so we can get rid of it.

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-12-06 11:41:04 +01:00
Guillaume Ballet
69576df254 .github: use github actions to run 32-bit linux tests (#28549)
use github actions to run 32-bit linux tests
2023-12-05 14:45:40 +01:00
Martin Holst Swende
b8d44ed98b log: remove lazy, remove unused interfaces, unexport methods (#28622)
This change 

- Removes interface `log.Format`, 
- Removes method `log.FormatFunc`, 
- unexports `TerminalHandler.TerminalFormat` formatting methods (renamed to `TerminalHandler.format`)
- removes the notion of `log.Lazy` values


The lazy handler was useful in the old log package, since it
could defer the evaluation of costly attributes until later in the
log pipeline: thus, if the logging was done at 'Trace', we could
skip evaluation if logging only was set to 'Info'.

With the move to slog, this way of deferring evaluation is no longer
needed, since slog introduced 'Enabled': the caller can thus do
the evaluate-or-not decision at the callsite, which is much more
straight-forward than dealing with lazy reflect-based evaluation.

Also, lazy evaluation would not work with 'native' slog, as in, these
two statements would be evaluated differently:

```golang
  log.Info("foo", "my lazy", lazyObj)
  slog.Info("foo", "my lazy", lazyObj)
```
2023-12-05 11:54:44 +01:00
Martin Holst Swende
3dc071e036 eth/tracers/logger: make structlog/json-log stack hex again (#28628)
* common/hexutil: define hex wrappers for uint256.Int

* eth/tracers/logger: make structlog/json-log stack hex again

* common/hexutil: goimports
2023-12-05 09:37:48 +01:00
Håvard Anda Estensen
2e13b01046 accounts: run tests in parallel (#28544) 2023-12-04 14:55:06 +01:00
Manav Darji
70fd0b635e eth/fetcher: fix invalid tracking of received at time for block (#28637)
eth/fetcher: fix invalid tracking of received at time
2023-12-04 14:25:17 +02:00
BorkBorked
f04e5bde74 accounts/abi/bind: fixed typos (#28634)
* Update auth.go

* Update backend.go

* Update bind.go

* Update bind_test.go
2023-12-04 11:53:42 +02:00
ddl
6e488c2449 cmd/evm: fix Env struct json tag (#28635) 2023-12-04 11:52:55 +02:00
Delweng
5fb8ebc9ec eth/tracers: tx-level state in debug_traceCall (#28460) 2023-12-01 16:38:52 +03:30
Martin Holst Swende
dd0d0a2522 slog: faster and less memory-consumption (#28621)
These changes improves the performance of the non-coloured terminal formatting, _quite a lot_. 

```
name               old time/op    new time/op    delta
TerminalHandler-8    10.2µs ±15%     5.4µs ± 9%  -47.02%  (p=0.008 n=5+5)

name               old alloc/op   new alloc/op   delta
TerminalHandler-8    2.17kB ± 0%    0.40kB ± 0%  -81.46%  (p=0.008 n=5+5)

name               old allocs/op  new allocs/op  delta
TerminalHandler-8      33.0 ± 0%       5.0 ± 0%  -84.85%  (p=0.008 n=5+5)
```

I tried to _somewhat_ organize the commits, but the it might still be a bit chaotic. Some core insights: 

- The function `terminalHandler.Handl` uses a mutex, and writes all output immediately to 'upstream'. Thus, it can reuse a scratch-buffer every time. 
- This buffer can be propagated internally, making all the internal formatters either write directly to it,
- OR, make  use of the `tmp := buf.AvailableBuffer()` in some cases, where a byte buffer "extra capacity" can be temporarily used. 
- The `slog` package  uses `Attr` by value. It makes sense to minimize operating on them, since iterating / collecting into a new slice, iterating again etc causes copy-on-heap. Better to operate on them only once. 
- If we want to do padding, it's better to copy from a constant `space`-buffer than to invoke `bytes.Repeat` every single time.
2023-12-01 13:28:20 +01:00
BorkBorked
f2b509d8a1 accounts/abi/bind: fix typo (#28630) 2023-12-01 09:51:50 +01:00
Maciej Kulawik
fa0df76f3c trie/triedb/hashdb: take lock around access to dirties cache (#28542)
Add read locking of db lock around access to dirties cache in hashdb.Database to prevent
data race versus hashdb.Database.dereference which can modify the dirities map by deleting
an item.

Fixes #28541

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-11-30 10:50:48 +01:00
rjl493456442
ab0eb46a84 core/state: make stateobject.create selfcontain (#28459) 2023-11-29 16:07:51 +08:00
jwasinger
28e7371701 all: replace log15 with slog (#28187)
This PR replaces Geth's logger package (a fork of [log15](https://github.com/inconshreveable/log15)) with an implementation using slog, a logging library included as part of the Go standard library as of Go1.21.

Main changes are as follows:
* removes any log handlers that were unused in the Geth codebase.
* Json, logfmt, and terminal formatters are now slog handlers.
* Verbosity level constants are changed to match slog constant values.  Internal translation is done to make this opaque to the user and backwards compatible with existing `--verbosity` and `--vmodule` options.
* `--log.backtraceat` and `--log.debug` are removed.

The external-facing API is largely the same as the existing Geth logger.  Logger method signatures remain unchanged.

A small semantic difference is that a `Handler` can only be set once per `Logger` and not changed dynamically.  This just means that a new logger must be instantiated every time the handler of the root logger is changed.

----
For users of the `go-ethereum/log` module. If you were using this module for your own project, you will need to change the initialization. If you previously did 
```golang
log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
```
You now instead need to do 
```golang
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
```
See more about reasoning here: https://github.com/ethereum/go-ethereum/issues/28558#issuecomment-1820606613
2023-11-29 08:33:50 +01:00
Péter Szilágyi
61b844f2b2 eth/gasestimator: allow slight estimation error in favor of less iterations (#28618)
* eth/gasestimator: early exit for plain transfer and error allowance

* core, eth/gasestimator: hard guess at a possible required gas

* internal/ethapi: update estimation tests with the error ratio

* eth/gasestimator: I hate you linter

* graphql: fix gas estimation test

---------

Co-authored-by: Oren <orenyomtov@users.noreply.github.com>
2023-11-28 22:31:47 +02:00
Jakub Freebit
e0c7ad01ab consensus: verify the nonexistence of shanghai- and cancun-specific header fields (#28605) 2023-11-28 21:29:00 +01:00
Guillaume Ballet
34dcd74935 crypto/secp256k1: fix 32-bit tests when CGO_ENABLED=0 (#28602) 2023-11-28 19:16:50 +01:00
Sina Mahmoodi
bbc5db8405 eth/tracers/js: fix type inconsistencies (#28488)
This change fixes two type-inconsistencies in the JS tracer:

- In most places we return byte arrays as a `Uint8Array` to the tracer. However it seems we missed doing the conversion for `ctx` fields which are passed to the tracer during `result`. They are passed as simple arrays. I think Uint8Arrays are more suitable and we should change this inconsistency. Note: this will be a breaking-change. But I believe the effect is small. If we look at our tracers we see that these fields (`ctx.from`, `ctx.to`, etc.) are used in 2 ways. Passed to `toHex` which takes both array or buffer. Or the length was measured which is the same for both types.
- The `slice` taking in `int, int` params versus `memory.slice` taking `int64, int64` params. I suggest changing `slice` types to `int64`. This should have no effect almost in any case.
2023-11-28 15:00:35 +01:00
Shivam Sandbhor
248dc50ee8 ethereum: remove TODO comment about subscription (#28609) 2023-11-28 14:49:08 +01:00
Martin Holst Swende
63979bc9cc cmd/evm, core/state: fix post-exec dump of state (statetests, blockchaintests) (#28504)
There were several problems related to dumping state. 

- If a preimage was missing, even if we had set the `OnlyWithAddresses` to `false`, to export them anyway, the way the mapping was constructed (using `common.Address` as key) made the entries get lost anyway. Concerns both state- and blockchain tests. 
- Blockchain test execution was not configured to store preimages.

This changes makes it so that the block test executor takes a callback, just like the state test executor already does. This callback can be used to examine the post-execution state, e.g. to aid debugging of test failures.
2023-11-28 13:54:17 +01:00
lightclient
58297e339b light: remove package light(#28614)
This changes removes the package 'light', which is currently unused.
2023-11-28 09:01:23 +01:00
rjl493456442
71817f318e eth/catalyst, eth/downloader: expose more sync information (#28584)
This change exposes more information from sync module internally
2023-11-28 08:38:30 +01:00
Martin Holst Swende
5b57727d6d go.mod: update uint256 to v1.2.4 (#28612) 2023-11-27 16:39:28 +02:00
Péter Szilágyi
1e28e0bb03 eth/gasestimator, internal/ethapi: move gas estimator out of rpc (#28600) 2023-11-27 16:20:09 +02:00
Ng Wei Han
333dd956bf trie: fix random test generator early terminate (#28590)
This change fixes a minor bug in the `randTest.Generate` function, which caused the `quick.Check` to be a no-op.
2023-11-25 14:56:22 +01:00
Péter Szilágyi
2a2013014c eth, internal/ethapi: drop some weird indirection (#28597) 2023-11-24 13:26:42 +02:00
Marius van der Wijden
bdf5e388ca cmd, les, tests: remove light client code (#28586)
* cmd, les, tests: remove light client code

This commit removes the light client (LES) code.
Since the merge the light client has been broken and
it is hard to maintain it alongside the normal client.
We decided it would be best to remove it for now and
maybe rework and reintroduce it in the future.

* cmd, eth: remove some more mentions of light mode

* cmd: re-add flags and mark as deprecated

* cmd: warn the user about deprecated flags

* eth: better error message
2023-11-23 16:28:26 +02:00
Mikel Cortes
d76efbb9be params: update discV5 bootnodes (#28562)
update discV5 bootnodes from https://github.com/eth-clients/eth2-networks/blob/master/shared/mainnet/bootstrap_nodes.txt
2023-11-23 11:14:10 +01:00
Martin Holst Swende
eec37e3b71 cmd/devp2p/internal/ethtest: undo debug-hack (#28588)
cmd/devp2p/internal/ethtest: remove a debug-hack flaw which prevented certain tests from running
2023-11-23 09:22:09 +01:00
Felix Lange
63127f5443 cmd/geth: fix build error (#28585) 2023-11-22 16:32:43 +01:00
Guillaume Ballet
d468c333a7 cmd/{geth,utils}: add cmd to export preimages in snap enumeration order (#28256)
Adds a subcommand: `geth snapshot export-preimages`, to export preimages of every hash found during a snapshot enumeration: that is, it exports _only the active state_, and not _all_ preimages that have been used but are no longer part of the state. 

This tool is needed for the verkle transition, in order to distribute the preimages needed for the conversion. Since only the 'active' preimages are exported, the output is shrunk from ~70GB to ~4GB.

The order of the output is the order used by the snapshot enumeration, which avoids database thrashing. However, it also means that storage-slot preimages are not deduplicated.
2023-11-22 14:48:25 +01:00
Håvard Anda Estensen
5ff929c22f les/vflux: run tests in parallel (#28524) 2023-11-22 14:00:30 +01:00
jwasinger
3cfcd252db cmd/geth: add support for --dev flag in dumpgenesis (#28463)
Co-authored-by: Felix Lange <fjl@twurst.com>
Co-authored-by: lightclient <lightclient@protonmail.com>
2023-11-22 12:08:39 +01:00
jwasinger
104dbf7821 cmd/utils: validate pre-existing genesis in --dev mode (#28468)
geth --dev can be used with an existing data directory and genesis block. Since
dev mode only works with PoS, we need to verify that the merge has happened.

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-11-22 12:01:38 +01:00
Delweng
d6cea4832a rpc: improve performance of subscription notification encoding (#28328)
It turns out that encoding json.RawMessage is slow because
package json basically parses the message again to ensure it is valid.
We can avoid the slowdown by encoding the entire RPC notification once,
which yields a 30% speedup.
2023-11-22 11:24:54 +01:00
Mario Vega
347fecd881 core/types: make 'v' optional for DynamicFeeTx and BlobTx (#28564)
This fixes an issue where transactions would not be accepted when they have only
'yParity' and not 'v'.
2023-11-22 11:00:44 +01:00
ucwong
e9f59b5d5e eth/filters: reuse error msg for invalid block range (#28479) 2023-11-21 15:28:44 +01:00
Maciej Kulawik
6489a0dd1f ethdb/pebble: don't double-close iterator inside pebbleIterator (#28566)
Adds 'released' flag to pebbleIterator to avoid double closing cockroachdb/pebble.Iterator as it is an invalid operation.

Fixes #28565
2023-11-21 15:22:22 +01:00
Marius van der Wijden
146e8d999c core, trie, rpc: speed up tests (#28461)
* rpc: make subscription test faster

reduces time for TestClientSubscriptionChannelClose
from 25 sec to < 1 sec.

* trie: cache trie nodes for faster sanity check

This reduces the time spent on TestIncompleteSyncHash
from ~25s to ~16s.

* core/forkid: speed up validation test

This takes the validation test from > 5s to sub 1 sec

* core/state: improve snapshot test run
brings the time for TestSnapshotRandom from 13s down to 6s

* accounts/keystore: improve keyfile test

This removes some unnecessary waits and reduces the
runtime of TestUpdatedKeyfileContents from 5 to 3 seconds

* trie: remove resolver
* trie: only check ~5% of all trie nodes
2023-11-21 12:19:28 +01:00
levisyin
525db7b2c5 accounts/abi: context info on unpack-errors (#28529)
adds contextual information to errors returned by unpack
2023-11-21 09:16:57 +01:00
Haotian
ad16f11f84 cmd/evm: capitalize evm commands (#28569)
* standard:fix for a unified standard

* standard:fix more as a complements

---------

Co-authored-by: haotian <haotian@haotiandeMacBook-Air.local>
2023-11-21 09:56:23 +02:00
rjl493456442
661bd45188 core/state/snapshot: print correct error from trie iterator (#28560) 2023-11-21 10:47:37 +08:00
Håvard Anda Estensen
460cc1673e cmd: run tests in parallel (#28546) 2023-11-20 10:52:14 +01:00
jp-imx
14a1e96b68 core/txpool/legacypool: respect nolocals-setting (#28435)
This change adds a check to ensure that transactions added to the legacy pool are not treated as 'locals' if the global locals-management has been disabled. 

This change makes the pool enforce the --txpool.pricelimit setting.
2023-11-20 09:05:20 +01:00
levisyin
a73748258f accounts, cmd: fix typos (#28526) 2023-11-20 08:44:05 +01:00
Håvard Anda Estensen
77cb21da2c signer: run tests in parallel (#28536)
marks tests as parallel-safe in package signer
2023-11-20 08:20:59 +01:00
danceratopz
c8a2202028 cmd/evm: validate blockchain tests poststate account storage (#28443)
This PR verifies the accounts' storage as specified in a blockchain test's postState field

The expect-section, it does really only check that the test works. It's meant for the test-author to verify that "If the test does what it's supposed to, then the nonce of X should be 2, and the slot Y at Z should be 0x123.

    This expect-section is not exhaustive (not full post-state)
    It is also not auto-generated, but put there manually by the author.

We can still check it, as a test-sanity-check, in geth
2023-11-17 15:56:21 +01:00
Håvard Anda Estensen
8b78d6a7a0 Dockerfile: update Go to 1.21 (#28538) 2023-11-17 16:48:06 +02:00
Martin Holst Swende
5bf8769fb0 ethdb/memorydb, trie: reduced allocations (#28473)
* trie: use pooling of iterator states in iterator

The node iterator burns through a lot of memory while iterating a trie, and a lot of
that can be avoided by using a fairly small pool (max 40 items).

name        old time/op    new time/op    delta
Iterator-8    6.22ms ± 3%    5.40ms ± 6%  -13.18%  (p=0.008 n=5+5)

name        old alloc/op   new alloc/op   delta
Iterator-8    2.36MB ± 0%    1.67MB ± 0%  -29.23%  (p=0.008 n=5+5)

name        old allocs/op  new allocs/op  delta
Iterator-8     37.0k ± 0%     29.8k ± 0%     ~     (p=0.079 n=4+5)

* ethdb/memorydb: avoid one copying of key

By making the transformation from []byte to string at an earlier point,
we save an allocation which otherwise happens later on.

name           old time/op    new time/op    delta
BatchAllocs-8     412µs ± 6%     382µs ± 2%   -7.18%  (p=0.016 n=5+4)

name           old alloc/op   new alloc/op   delta
BatchAllocs-8     480kB ± 0%     490kB ± 0%   +1.93%  (p=0.008 n=5+5)

name           old allocs/op  new allocs/op  delta
BatchAllocs-8     3.03k ± 0%     2.03k ± 0%  -32.98%  (p=0.008 n=5+5)
2023-11-15 16:20:34 +01:00
Håvard Anda Estensen
a75a2d6db6 all: replace some cases of strings.SplitN with strings.Cut (#28446) 2023-11-15 14:42:33 +01:00
Halimao
db7895d3b6 accounts/abi: improve readability of method-to-string conversion (#28530)
refactor: improve readability of NewMethod print
2023-11-15 14:30:35 +01:00
aliening
fcc7ae162d internal/jsre/deps: fix typo in jsdoc (#28511)
minor typo fix
2023-11-15 13:55:56 +01:00
Håvard Anda Estensen
b9504e4966 miner: run tests in parallel (#28506)
Changes many of the tests in the miner package to run in parallel
2023-11-15 13:46:32 +01:00
Zoro
2814ee0547 accounts,cmd,console,les,metrics: refactor some errors checked by (ST1005) go-staticcheck (#28532)
fix: fix some (ST1005)go-staticcheck
2023-11-15 14:36:57 +02:00
jwasinger
984f82629c cmd/geth: more special cases logging tests (#28527)
adds logging tests for errors and custom fmt.Stringer-types which output strings that needs to be quoted/escaped.
2023-11-15 09:54:35 +01:00
Martin Holst Swende
c5b7cfa9c3 tests: skip tests on windows 32bit CI (#28521)
tests: skip half the blockchain- and state-tests on windows 32bit CI-tests
2023-11-14 18:40:16 +01:00
Martin Holst Swende
2391fbc676 tests/fuzzers: move fuzzers into native packages (#28467)
This PR moves our fuzzers from tests/fuzzers into whatever their respective 'native' package is.

The historical reason why they were placed in an external location, is that when they were based on go-fuzz, they could not be "hidden" via the _test.go prefix. So in order to shove them away from the go-ethereum "production code", they were put aside.

But now we've rewritten them to be based on golang testing, and thus can be brought back. I've left (in tests/) the ones that are not production (bls128381), require non-standard imports (secp requires btcec, bn256 requires gnark/google/cloudflare deps).

This PR also adds a fuzzer for precompiled contracts, because why not.

This PR utilizes a newly rewritten replacement for go-118-fuzz-build, namely gofuzz-shim, which utilises the inputs from the fuzzing engine better.
2023-11-14 14:34:29 +01:00
VM
24d46224c1 trie: spelling - fix comments in hasher (#28507)
Co-authored-by: VM <arimas@foxmail.com>
2023-11-14 14:27:07 +01:00
Sina Mahmoodi
e803ef09ad eth/tracers/js: fix isPush for push0 (#28520)
Fixes so that `push0` opcode is correctly reported as `true` by the `IsPush` function

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-11-14 13:14:38 +01:00
Guillaume Ballet
fa8d39807d cmd, core, trie: verkle-capable geth init (#28270)
This change allows the creation of a genesis block for verkle testnets. This makes for a chunk of code that is easier to review and still touches many discussion points.
2023-11-14 13:09:40 +01:00
Péter Szilágyi
916d6a441a params: release Geth v1.15.5 2023-11-14 15:02:24 +03:00
Delweng
f265cc24b4 cmd/geth: remove some whitespace in code and comments (#28148)
This changes just removes some whitespace
2023-11-10 13:26:13 +01:00
Marius Kjærstad
49b2c5f43c build: upgrade -dlgo version to Go 1.21.4 (#28505) 2023-11-10 13:15:06 +01:00
Delweng
ce5a4809fd ethclient: add empty/nonexist account testcase for eth_getProof RPC (#28482)
Adds testcases for eth_getProof endpoint for the following cases: 

- the account/contract does not exist
- the account/contract exists but is empty.
2023-11-10 12:23:09 +01:00
Wei Tang
2f4833b828 cmd/evm: allow state dump regardless if test passes in statetest (#28484)
This change makes it so that when executing state tess, state is always dumped out if the corresponding flag is set.
2023-11-10 12:21:51 +01:00
rjl493456442
326fa00759 core/rawdb: fsync the index file after each freezer write (#28483)
* core/rawdb: fsync the index and data file after each freezer write

* core/rawdb: fsync the data file in freezer after write
2023-11-10 12:56:39 +02:00
Delweng
e38b9f1830 eth/filters: exit early if topics-filter has more than 4 topics (#28494)
Currently, geth's will return `[]` for any `len(topics) > 4` log filter. The EVM only supports up to four logs, via LOG4 opcode, so larger criterias fail. This change makes the filter query exit early in those cases.
2023-11-10 08:10:03 +01:00
Jim McDonald
f7dde2a96c ethdb/pebble: add Errorf function to panicLogger (#28491)
cockroachdb/pebble@422dce9 added Errorf to the Logger interface, this change makes it possible to compile geth with that version of pebble by adding the corresponding method to panicLogger.
2023-11-09 15:15:22 +01:00
Martin Holst Swende
b77a9b127c cmd/geth: more testcases for logging (#28501)
* cmd/geth: more testcases for logging

This adds more edgecases around logging, particularly around handling of different types of nil-values
as concrete types and within interfaces.

Also adds tests with 'reserved' values which breaks json/logfmt formats. The json output is checked in,
but not actively used by any testcase at the moment.

* cmd/geth/testdata: remove timestamps
2023-11-09 10:46:48 +01:00
Delweng
7ea860d665 graphql: type of yParity from Long to BigInt (#28456)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-11-09 11:36:27 +03:00
Péter Szilágyi
470dba8fc1 core/vm: set basefee to 0 internally on eth_call (#28470)
* core/vm: set basefee to 0 internally on eth_call

* core: nicer 0-basefee, make it work for blob fees too

* internal/ethapi: make tests a bit more complex

* core: fix blob fee checker

* core: make code a bit more readable

* core: fix some test error strings

* core/vm: Get rid of weird comment

* core: dict wrong typo
2023-11-08 11:22:08 +02:00
Marius van der Wijden
4d9f3cd5d7 eth: set networkID to chainID by default (#28250)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-11-07 14:21:46 +01:00
Delweng
f20b334f21 eth/filters: eth_getLogs fast exit for invalid block range (#28386) 2023-11-07 12:41:19 +01:00
Péter Szilágyi
97ae32441e travis: use newer builder image (#28475) 2023-11-07 13:00:31 +02:00
Péter Szilágyi
51b5ad3da3 .travis: enable cross building to macos arm64 (#28474)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-11-07 11:35:03 +01:00
Péter Szilágyi
e91cdb49be ethclient: fix forwarding 1559 gas fields (#28462) 2023-11-03 19:40:37 +02:00
Alvaro Sevilla
b1cec853be eth/tracers: add position field for callTracer logs (#28389)
Currently, one can use the "withLogs" parameter to include logs in the
callTracer results, which allows the user to see at which trace level
was each log emitted.
This commit adds a position field to the logs which determine
the exact ordering of a call's logs and its subcalls. This would
be useful e.g. for explorers wishing to display the flow of execution.

Co-authored-by: jsvisa <delweng@gmail.com>
2023-11-03 10:28:27 +01:00
lmittmann
a3be38127c core/vm: performance tweak of OpCode.String() (#28453)
make `opCodeToString` a `[256]string` array

Co-authored-by: lmittmann <lmittmann@users.noreply.github.com>
2023-11-02 08:54:28 +02:00
rjl493456442
f4ac548619 ethdb/pebble: cap memory table size as maxMemTableSize-1 (#28444) 2023-10-31 18:19:31 +02:00
Mario Vega
285202aae2 cmd/evm: add --run option to blocktest command (#28421)
Co-authored-by: lightclient <lightclient@protonmail.com>
2023-10-31 15:23:51 +01:00
Felix Lange
bc42e88415 core: add basic chain history support in GenerateChain (#28428)
This change improves GenerateChain to support internal chain history access (ChainReader)
for the consensus engine and EVM.

GenerateChain takes a `parent` block and the number of blocks to create. With my changes,
the consensus engine and EVM can now access blocks from `parent` up to the block currently
being generated. This is required to make the BLOCKHASH instruction work, and also needed
to create real clique chains.  Clique uses chain history to figure out if the current signer is in-turn,
for example.

I've also added some more accessors to BlockGen. These are helpful when creating transactions:

- g.Signer returns a signer instance for the current block
- g.Difficulty returns the current block difficulty
- g.Gas returns the remaining gas amount

Another fix in this commit concerns the receipts returned by GenerateChain. The receipts now
have properly derived fields (BlockHash, etc.) and should generally match what would be
returned by the RPC API.
2023-10-31 12:39:25 +01:00
Jakub Freebit
447945e438 core/rawdb: add logging and fix comments around AncientRange function. (#28379)
This adds warning logs when the read does not match the expected count.
We can also remove the size limit since the function documentation explicitly states
that callers should limit the count.
2023-10-31 12:04:45 +01:00
rjl493456442
ea2e66a58e trie/triedb/pathdb: improve dirty node flushing trigger (#28426)
* trie/triedb/pathdb: improve dirty node flushing trigger

* trie/triedb/pathdb: add tests

* trie/triedb/pathdb: address comment
2023-10-31 11:39:55 +02:00
Martin Holst Swende
233db64cc1 all: make vendored copy of reexec (#28382)
a little copying is better than a little dependency

-- go proverb

We have this dependency on docker, a.k.a moby: a gigantic library, and we only need ~70 LOC,
so here I tried moving it inline instead.

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-10-28 00:14:43 +02:00
Delweng
2d7dba024d graphql: always set content-type to application/json (#28417)
---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-10-27 16:50:59 +02:00
Guillaume Ballet
4cbca5178a core, cmd/geth: add --override.* flags to geth init (#28407)
* core, cmd/geth: add --override.* flags to geth init

* also apply overrides before genesis commit with new block

* review feedback
2023-10-27 10:15:14 +08:00
Delweng
abe3fca1de graphql: fix an issue of nil pointer panic (#28416)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-10-26 13:48:51 +02:00
Martin Holst Swende
58ae1df684 cmd/geth: test for logging-output (#28373)
This PR is a bit in preparation for the slog work in #28187 .

Our current test re logging mostly test the internals, but we have no real end-to-end test of the logging output. This PR introduces a simple reexec-based log tester. This also relies upon a special mode in geth, which can be made to eject a set of predefined log messages (only available if the build-tag `integrationtests` is used

e.g. go run --tags=integrationtests ./cmd/geth --log.format terminal logtest

While working on this, I also noticed a quirk in the setup: when geth was configured to use a file output, then two separate handlers were used (one handler for the file, one handler for the console). Using two separate handlers means that two formatters are used, thus the formatting of any/all records happened twice. This PR changes the mechanism to use two separate io.Writers instead, which is both more optimal and fixes a bug which occurs due to a global statefulness in the formatter.
2023-10-25 17:57:12 +02:00
Adrian Sutton
d8c6ae054c rpc: use correct stringer-method for serializing BlockNumberOrHash (#28358)
The String() version of BlockNumberOrHash uses decimal for all block numbers, including negative ones used to indicate labels. Switch to using BlockNumber.String() which encodes it correctly for use in the JSON-RPC API.
2023-10-25 15:52:42 +02:00
Delweng
f7b62e5506 graphql: logs return error if from block > to (#28412)
As per discussion in ethereum/execution-apis#475

Signed-off-by: jsvisa <delweng@gmail.com>
2023-10-25 15:20:23 +02:00
Martin Holst Swende
96b75033c0 trie: use explicit errors in stacktrie (instead of panic) (#28361)
This PR removes panics from stacktrie (mostly), and makes the Update return errors instead. While adding tests for this, I also found that one case of possible corruption was not caught, which is now fixed.
2023-10-25 14:53:50 +02:00
Martin Holst Swende
300df874d7 cmd/evm: make t8ntool handle transaction decoding errors better (#28397)
This change closes https://github.com/ethereum/go-ethereum/issues/27730 . By using an iterator instead of a slice of transactions, we can better handle the case when an individual transaction (within an otherwise well-formed RLP-list) cannot be decoded.
2023-10-25 14:08:52 +02:00
moomin
a8617c6d4d txpool/legacypool: remove already known error in legacypool (#28400) 2023-10-23 18:36:11 +03:00
rjl493456442
ab04aeb855 core, eth, trie: filter out boundary nodes and remove dangling nodes in stacktrie (#28327)
* core, eth, trie: filter out boundary nodes in stacktrie

* eth/protocol/snap: add comments

* Update trie/stacktrie.go

Co-authored-by: Martin Holst Swende <martin@swende.se>

* eth, trie: remove onBoundary callback

* eth/protocols/snap: keep complete boundary nodes

* eth/protocols/snap: skip healing if the storage trie is already complete

* eth, trie: add more metrics

* eth, trie: address comment

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-10-23 18:31:56 +03:00
Delweng
43e6a3c196 graphql: return error if block from>to (#28393)
As per discussion in ethereum/execution-apis#475
2023-10-23 17:25:26 +02:00
rjl493456442
3853f50082 trie/triedb/pathdb, core/rawdb: enhance error message in freezer (#28198)
This PR adds more error message for debugging purpose.
2023-10-23 15:46:39 +02:00
hyunchel
062598bb40 core/blockchain: fix typos and grammar (#28295) 2023-10-23 15:23:41 +02:00
kaliubuntu0206
54f35c68be ethstats: fix bug in block reporting (#28398)
Fixes a bug where the ethstats omits to report full block contents. This bug was a side-effect of https://github.com/ethereum/go-ethereum/pull/26777,  where `CurrentBlock` was changed to return a header instead of a block, leading to a failed type assertion.
2023-10-23 15:06:05 +02:00
aaronbuchwald
6c6982163b core/state/pruner: track number of skipped items during state pruning (#28368) 2023-10-23 13:24:32 +08:00
Inphi
ffc6a0f36e event: fix Resubscribe deadlock when unsubscribing after inner sub ends (#28359)
A goroutine is used to manage the lifetime of subscriptions managed by
resubscriptions. When the subscription ends with no error, the resub
goroutine ends as well. However, the resub goroutine needs to live
long enough to read from the unsub channel. Otheriwse, an Unsubscribe
call deadlocks when writing to the unsub channel.

This is fixed by adding a buffer to the unsub channel.
2023-10-22 17:37:56 +02:00
kevaundray
a6a0ae45b6 crypto/kzg4844: use the new trusted setup file and format (#28383)
Changes the trusted_setup to the one created during the kzg-ceremony. The trusted setup file can be found in the consensus specs: https://github.com/ethereum/consensus-specs/blob/dev/presets/mainnet/trusted_setups/trusted_setup_4096.json
---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2023-10-22 16:05:04 +02:00
Martin Holst Swende
c1d5a012ea core/state, tests: fix memory leak via fastcache (#28387)
This change fixes a memory leak, when running either state-tests or blockchain-tests, we allocate a `1MB` fastcache during snapshot generation. `fastcache` is a bit special, and requires a `Reset()` (it has it's own memory allocator). 

The `1MB` was hidden [here](https://github.com/ethereum/go-ethereum/blob/master/tests/state_test_util.go#L333) and [here](https://github.com/ethereum/go-ethereum/blob/master/tests/block_test_util.go#L146) respectively.
2023-10-20 13:35:49 +02:00
Marius van der Wijden
cd29535672 crypto/blake2b: put architecture-dependent features behind build-tag (#28381)
This change to fixes a compilation-flaw on master, by putting architecture-specific functions behind corresponding build tags.
2023-10-19 14:04:26 +02:00
Sina Mahmoodi
4d3c0d41f4 eth/filters: fix flaky test TestPendingTxFilterDeadlock (#28376) 2023-10-19 10:30:55 +02:00
Brandon Liu
ec1a0502bf rpc: increase timeout in TestClientWebsocketPing (#28371) 2023-10-19 10:08:36 +02:00
Marius van der Wijden
d10a2f6ab7 tests/fuzzers: update fuzzers to be based on go-native fuzzing (#28352)
This change modifies the fuzzers to use the native golang fuzzing framework instead of go-fuzz
2023-10-18 15:01:16 +02:00
lightclient
da55b23d21 eth/fetcher: downgrade stale txs log from warn to debug (#28364) 2023-10-17 19:52:53 +03:00
Marius van der Wijden
d782dc2341 tests/fuzzers/les: fix crash in fuzzer (#28362) 2023-10-17 15:20:22 +02:00
lightclient
20d5256e40 core/chain_makers: add SetParentBeaconRoot(..) to chain makers (#28252) 2023-10-17 14:43:46 +02:00
Adrian Sutton
b85c86022e api/bind: add CallOpts.BlockHash to allow calling contracts at a specific block hash (#28084)
* api/bind: Add CallOpts.BlockHash to allow calling contracts at a specific block hash.

* ethclient: Add BalanceAtHash, NonceAtHash and StorageAtHash functions
2023-10-17 15:34:01 +03:00
Brandon Liu
f62502e123 internal/ethapi, accounts/abi/bind: use errors.Is for error comparison (#28348)
Co-authored-by: lightclient <lightclient@protonmail.com>
2023-10-17 14:11:04 +02:00
Kero
1f11d2d340 ethclient: ensure the close of canceled context (#28349) 2023-10-17 14:09:48 +02:00
rjl493456442
1b1611b8d0 core, trie, eth: refactor stacktrie constructor (#28350)
This change enhances the stacktrie constructor by introducing an option struct. It also simplifies the `Hash` and `Commit` operations, getting rid of the special handling round root node.
2023-10-17 14:09:25 +02:00
Péter Szilágyi
aeb0abf80a params: begin v1.13.5 release cycle 2023-10-17 14:18:45 +03:00
Péter Szilágyi
3f907d6a6f params: release Geth v1.13.4 2023-10-17 14:17:27 +03:00
Marius van der Wijden
667966c5c1 eth/fetcher: fix fetcher timeout (#28220)
This changes fixes a bug in the fetcher, where the timeout for how long to remember underpriced transaction was erroneously compared, and the timeout never hit.
---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-10-17 10:38:00 +02:00
xiaolou86
00c63830e4 cmd: fix typos (#28323) 2023-10-17 15:53:10 +08:00
Martin Holst Swende
8b99ad4602 internal/ethapi: fix codehash lookup in eth_getProof (#28357)
This change fixes #28355, where eth_getProof failed to return the correct codehash under certain conditions. This PR changes the logic to unconditionally look up the codehash, and also adds some more tests.
2023-10-17 09:25:16 +02:00
phenix3443
a5544d35f6 fix: broken url link (#28342) 2023-10-17 14:32:35 +08:00
Péter Szilágyi
2e478aab98 eth/fetcher: only make noise big mismatches (#28356) 2023-10-16 23:40:25 +03:00
Martin Holst Swende
4632b7b31e tests: update execution-spec-tests to 1.0.5 (#28337)
Updates execution-spec-tests to 1.0.5: https://github.com/ethereum/execution-spec-tests/releases/tag/v1.0.5, switching to develop which contains Cancun tests (which are also enabled in this change).
2023-10-16 20:10:05 +02:00
Péter Szilágyi
509a64ffb9 cmd, core, ethdb: enable Pebble on 32 bits and OpenBSD too (#28335)
* cmd, core, ethdb: enable Pebble on 32 bits and OpenBSD too

* ethdb/pebble: use Pebble's internal constant calculation
2023-10-13 22:50:20 +03:00
Péter Szilágyi
425cb6f65d go.mod: pull in the latest cloudflare API libs (#28336) 2023-10-13 17:08:38 +03:00
Martin Holst Swende
f62c58f8de trie: make rhs-proof align with last key in range proofs (#28311)
During snap-sync, we request ranges of values: either a range of accounts or a range of storage values. For any large trie, e.g. the main account trie or a large storage trie, we cannot fetch everything at once.

Short version; we split it up and request in multiple stages. To do so, we use an origin field, to say "Give me all storage key/values where key > 0x20000000000000000". When the server fulfils this, the server provides the first key after origin, let's say 0x2e030000000000000 -- never providing the exact origin. However, the client-side needs to be able to verify that the 0x2e03.. indeed is the first one after 0x2000.., and therefore the attached proof concerns the origin, not the first key.

So, short-short version: the left-hand side of the proof relates to the origin, and is free-standing from the first leaf.

On the other hand, (pun intended), the right-hand side, there's no such 'gap' between "along what path does the proof walk" and the last provided leaf. The proof must prove the last element (unless there are no elements).

Therefore, we can simplify the semantics for trie.VerifyRangeProof by removing an argument. This doesn't make much difference in practice, but makes it so that we can remove some tests. The reason I am raising this is that the upcoming stacktrie-based verifier does not support such fancy features as standalone right-hand borders.
2023-10-13 16:05:29 +02:00
Péter Szilágyi
31b566f7a8 go.mod: update AWS APIs to latest heads (#28332) 2023-10-13 15:19:03 +03:00
Martin Holst Swende
ed5da55149 build: move version-info into checksum file (#28324)
* build: upgrade to golang 1.21.2

* build: verify checksums via tool

* deps: upgrade go to 1.21.3

* build: move more build metadata into checksum file

* build: move gobootsrc to checksums
2023-10-13 15:14:48 +03:00
Péter Szilágyi
660cbe4117 go.mod: update fastcache to latest (#28334) 2023-10-13 15:13:34 +03:00
Péter Szilágyi
78c8e1060c go.mod: update gnark lib to fix a malleability issue (#28333) 2023-10-13 13:49:40 +03:00
Péter Szilágyi
1f30cae4ad go.mod, internal/build: update Azure dependencies (#28329) 2023-10-13 12:58:07 +03:00
rjl493456442
1cb3b6aee4 eth/protocols/snap: fix snap sync failure on empty storage range (#28306)
This change addresses an issue in snap sync, specifically when the entire sync process can be halted due to an encountered empty storage range.

Currently, on the snap sync client side, the response to an empty (partial) storage range is discarded as a non-delivery. However, this response can be a valid response, when the particular range requested does not contain any slots.

For instance, consider a large contract where the entire key space is divided into 16 chunks, and there are no available slots in the last chunk [0xf] -> [end]. When the node receives a request for this particular range, the response includes:

    The proof with origin [0xf]
    A nil storage slot set

If we simply discard this response, the finalization of the last range will be skipped, halting the entire sync process indefinitely. The test case TestSyncWithUnevenStorage can reproduce the scenario described above.

In addition, this change also defines the common variables MaxAddress and MaxHash.
2023-10-13 09:08:26 +02:00
Péter Szilágyi
2f66d7c47c params: begin v1.13.4 release cycle 2023-10-12 14:39:10 +03:00
Péter Szilágyi
0d45d72d70 params: release Geth v.1.13.3 2023-10-12 14:36:49 +03:00
Martin Holst Swende
d2c0bed9d5 cmd/geth: fix failing test (#28322) 2023-10-12 09:54:00 +02:00
vuittont60
0004c6b229 accounts, cmd: fix typos (#28300) 2023-10-11 11:29:10 +03:00
rjl493456442
eeb5dc3ccf cmd, core: resolve scheme from a read-write database (#28313)
* cmd, core: resolve scheme from a read-write database

* cmd, core, eth: move the scheme check in the ethereum constructor

* cmd/geth: dump should in ro mode

* cmd: reverts
2023-10-11 11:27:44 +03:00
Péter Szilágyi
13d1d425ac eth/fetcher: fix typo 2023-10-11 11:23:57 +03:00
Péter Szilágyi
a6deb2d994 eth/fetcher: throttle tx fetches to 128KB responses (#28304)
* eth/fetcher: throttle tx fetches to 128KB responses

* eth/fetcher: unindent a clause per review request
2023-10-11 10:50:09 +03:00
rjl493456442
7776a3214a ethdb/pebble: add level file metrics (#28271) 2023-10-11 09:18:18 +02:00
Martin Holst Swende
8976a0c97a trie: remove owner and binary marshaling from stacktrie (#28291)
This change
  - Removes the owner-notion from a stacktrie; the owner is only ever needed for comitting to the database, but the commit-function, the `writeFn` is provided by the caller, so the caller can just set the owner into the `writeFn` instead of having it passed through the stacktrie.
  - Removes the `encoding.BinaryMarshaler`/`encoding.BinaryUnmarshaler` interface from stacktrie. We're not using it, and it is doubtful whether anyone downstream is either.
2023-10-11 06:12:45 +02:00
Péter Szilágyi
2c007cfed7 accounts/abi/bind/backend: use requested header for gas prices and gas limits (#28280) 2023-10-10 15:53:01 +03:00
lightclient
5e43ed0d72 git: ignore tests/spec-tests folder (#28254) 2023-10-10 10:56:50 +02:00
Péter Szilágyi
8afbcf4713 eth: enforce announcement metadatas and drop peers violating the protocol (#28261)
* eth: enforce announcement metadatas and drop peers violating the protocol

* eth/fetcher: relax eth/68 validation a bit for flakey clients

* tests/fuzzers/txfetcher: pull in suggestion from Marius

* eth/fetcher: add tests for peer dropping

* eth/fetcher: linter linter linter linter linter
2023-10-10 11:35:51 +03:00
Brandon Liu
6505297456 trie: fix a typo, use correct docstrings (#28302)
* fix a typo

* trie: additional fixes to docstrings

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-10-10 10:32:14 +02:00
Martin Holst Swende
6b1e4f4211 all: move light.NodeSet to trienode.ProofSet (#28287)
This is a minor refactor in preparation of changes to range verifier. This PR contains no intentional functional changes but moves (and renames) the light.NodeSet
2023-10-10 10:30:47 +02:00
hyunchel
db9afae2ea eth, params: fix typos (#28286)
* eth/ethconfig: fix typo on comment

* params/config: fix typo on comment

* eth/ethconfig: fix typo on comment
2023-10-10 10:22:45 +02:00
0xbstn
fa6107c85e core: fix typos (#28255)
fixes various typos in core
2023-10-10 10:22:03 +02:00
Martin Holst Swende
08326794e8 trie: refactor stacktrie (#28233)
This change refactors stacktrie to separate the stacktrie itself from the
internal representation of nodes: a stacktrie is not a recursive structure
of stacktries, rather, a framework for representing and operating upon a set of nodes.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-10-10 08:28:56 +02:00
hyunchel
4e1e37323d core/txpool/legacypool: fix typo (#28258) 2023-10-07 10:57:12 +08:00
tactical_retreat
052355f5e2 cmd/evm/internal/t8ntoo: tiny bugfix for difficulty field (#28245) 2023-10-04 12:38:25 +03:00
Péter Szilágyi
95b0555c84 eth: when snap is complaining for missing eth, be verbose about the details (#28249)
* eth: when snap is complaining for missing eth, be verbost about the details

* eth: lower snapshot registration error verbosity
2023-10-04 12:37:04 +03:00
Péter Szilágyi
a8a9c8e4b0 core, eth, miner: start propagating and consuming blob txs (#28243)
* core, eth, miner: start propagating and consuming blob txs

* eth/protocols/eth: disable eth/67 if Cancun is enabled

* core/txpool, eth, miner: pass gas limit infos in lazy tx for mienr filtering

* core/txpool, miner: add lazy resolver for pending txs too

* core, eth: fix review noticed bugs

* eth, miner: minor polishes in the mining and announcing logs

* core/expool: unsubscribe the event scope
2023-10-04 12:36:36 +03:00
Péter Szilágyi
bc6d184872 cmd/devp2p, eth: drop eth/66 (#28239)
* cmd/devp2p, eth: drop eth/66

* eth/protocols/eth: yes sir, linter
2023-10-03 15:03:19 +03:00
hyunchel
7963c4e808 rpc: fix erroneous error-message in test (#28227) 2023-10-03 07:48:36 -04:00
Chirag Garg
2091ebdf5e trie: fix benchmark by ensuring key immutability (#28221)
This change fixes the bug in a benchmark, where the input to the trie is reused in a way which is not correct. 

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-10-03 07:46:22 -04:00
0xbstn
339a4cf056 core: fix typos (#28238) 2023-10-03 07:44:01 -04:00
lightclient
07dec7a11c cmd/evm: cancun-updates for b11r and t8n -tools (#28195)
This change updates `evm b11r` (blockbuilder) and `evm t8n` (transition) tools to contain cancun updates (e.g. new header fields)
---------

Co-authored-by: Mario Vega <marioevz@gmail.com>
2023-10-03 03:26:33 -04:00
tylerni7
705a51e566 eth, rpc: add configurable option for wsMessageSizeLimit (#27801)
This change adds a configurable limit to websocket message. 
---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-10-03 03:23:19 -04:00
Marius van der Wijden
c39cbc1a78 core: implement BLOBBASEFEE opcode (0x4a) (#28098)
Implements "EIP-7516: BLOBBASEFEE opcode" for cancun, as per spec: https://eips.ethereum.org/EIPS/eip-7516
2023-10-02 05:49:29 -04:00
Péter Szilágyi
7b6ff527d5 cmd, eth: switch the dev synctarget to hash from block (#28209)
* cmd, eth: switch the dev synctarget to hash from block

* cmd/utils, eth/catalyst: terminate node wyen synctarget reached
2023-09-29 22:11:15 +03:00
lightclient
a408e37fa1 eth/catalyst: add validation error in new paylaod hash mismatch (#28226)
* eth/catalyst: add validation error in new paylaod hash mismatch

* eth/catalyst/api: refactor api.invalid(..) to return nil latest valid hash if none provided
2023-09-29 21:27:30 +03:00
Péter Szilágyi
966e50bddb ethdb/pebble: luv you linter 2023-09-29 20:52:55 +03:00
rjl493456442
22dcb7a77b ethdb/pebble: upgrade pebble to master (aa077af62593) (#28070)
* ethdb/pebble: upgrade pebble

* ethdb/pebble, go.mod: update pebble to master (aa077af62593)

---------

Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-09-29 20:45:38 +03:00
Péter Szilágyi
1f9d672df1 common: remove address.Hash footgun (#28228) 2023-09-29 18:14:26 +03:00
aaronbuchwald
c5ff839fb2 core/state: small trie prefetcher nits (#28183)
Small trie prefetcher nits
2023-09-29 17:46:23 +03:00
Sina Mahmoodi
0ded110b80 core: infer blobGasUsed in chain maker (#28212)
Same way that the gasUsed in header is updated when a tx 
is added we should update blob gas used instead of requiring caller
to set it manually.
2023-09-29 10:44:28 +02:00
0xbstn
1f6e63900d core: fix typos (#28218)
* fix(core/txpool): fix typos

* core/asm: fix typos

* core/bloombits: fix typos

* core/rawdb: fix typos
2023-09-29 10:52:22 +03:00
Péter Szilágyi
f988b2332e ethdb, internal/ethapi: support exposing Pebble stats too, beside LevelDB (#28224)
ethdb, internal/ethapi: support exposing Pebble stats too, besinde LevelDB
2023-09-28 22:27:21 +03:00
phenix3443
b9450bfcca core, eth: typos and some code formatting (#28201)
* fix: typo

* feat: revert symbol name
2023-09-28 13:15:50 +03:00
Delweng
46c850a941 internal/ethapi: compact db missing key starts with 0xff (#28207)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-09-28 12:04:45 +03:00
lightclient
37a2d919b0 params: update 4788 beacon roots contract addr (#28205)
This change contains the final (?) address for 4788 beacon root contract. The update to the EIP is being tracked here: https://github.com/ethereum/EIPs/pull/7672

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-09-28 03:52:27 -04:00
Péter Szilágyi
3dc45a3e1d params: begin v1.13.3 release cycle 2023-09-28 10:23:25 +03:00
Péter Szilágyi
dc34fe8291 params: release Geth v1.13.2 2023-09-28 10:22:09 +03:00
rjl493456442
73f5bcb75b core, accounts, eth, trie: handle genesis state missing (#28171)
* core, accounts, eth, trie: handle genesis state missing

* core, eth, trie: polish

* core: manage txpool subscription in mainpool

* eth/backend: fix test

* cmd, eth: fix test

* core/rawdb, trie/triedb/pathdb: address comments

* eth, trie: address comments

* eth: inline the function

* eth: use synced flag

* core/txpool: revert changes in txpool

* core, eth, trie: rename functions
2023-09-28 10:00:53 +03:00
0xbstn
a081130081 core/txpool: fix typos (#28213)
fix(core/txpool): fix typos
2023-09-28 09:48:14 +08:00
bnovil
614804b33c core/txpool: fix typos (#28208)
core/txpool:fix typos
2023-09-27 11:08:53 +08:00
rjl493456442
b85c183ea7 eth/downloader: remove header rollback mechanism (#28147)
* eth/downloader: remove rollback mechanism in downloader

* eth/downloader: remove the tests
2023-09-26 16:29:13 +03:00
Sina Mahmoodi
adb9b319c9 internal/ethapi: eth_call block parameter is optional (#28165)
So apparently in the spec the base block parameter of eth_call is optional.
I agree that "latest" is a sane default for this that most people would use.
2023-09-26 14:22:11 +02:00
Marius van der Wijden
2b7bc2c36b eth/fetcher: allow underpriced transactions in after timeout (#28097)
This PR will allow a previously underpriced transaction back in after a timeout
of 5 minutes. This will block most transaction spam but allow for transactions to
be re-broadcasted on networks with less transaction flow.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-09-26 13:12:44 +02:00
phenix3443
40219109b0 eth/downloader: typo in comment (#28196) 2023-09-26 11:59:41 +03:00
hzysvilla
4de89e92e4 core/vm: minor code formatting (#28199)
Adding a space beween function opOrigin() and opcCaller() in instruciton.go.
Adding a space beween function opkeccak256()  and opAddress() in instruciton.go.
2023-09-26 11:58:01 +03:00
Andryanau Kanstantsin
4985d83b8f ethclient: fix BlockReceipts parameter encoding (#28087)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-09-25 23:24:20 +02:00
buddho
f6f64cc43d cmd/utils: fix bootnodes config priority (#28095)
This fixes an issue where the --bootnodes flag was overridden by the config file.

---------

Co-authored-by: NathanBSC <Nathan.l@nodereal.io>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-09-25 19:17:39 +02:00
Delweng
3d297fc2d7 cmd/geth: ensure db is closed before exit (#28150) 2023-09-25 18:28:20 +02:00
Felix Lange
c3742a9ae0 internal/debug: add --log.rotate to the logging category (#28190) 2023-09-25 17:02:44 +03:00
Marius van der Wijden
1fa3362ea7 core/forkid: add forkid test for holesky (#28193) 2023-09-25 17:02:19 +03:00
tokikuch
c2cfe35f12 core/bloombits: fix deadlock when matcher session hits an error (#28184)
When MatcherSession encounters an error, it attempts to close the session.
Closing waits for all goroutines to finish, including the 'distributor'. However, the
distributor will not exit until all requests have returned.

This patch fixes the issue by delivering the (empty) result to the distributor
before calling Close().
2023-09-25 15:35:24 +02:00
Péter Szilágyi
d051ea5e89 params: update hash for Holesky relaunch (#28192) 2023-09-25 16:13:56 +03:00
Péter Szilágyi
323542af50 core, params: update Holesky testnet to relaunched spec (#28191) 2023-09-25 16:10:23 +03:00
Péter Szilágyi
82ec555d70 cmd: add state.scheme to the database flag group for local flag handling (#28107) 2023-09-22 14:56:48 +03:00
Delweng
f1b2ec0833 core/rawdb: use readonly file lock in readonly mode (#28180)
This allows using the freezer from multiple processes at once
in read-only mode.

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-09-22 12:10:50 +02:00
Péter Szilágyi
d135bafdcb cmd/geth: print progress logs when iterating large contracts too (#28179) 2023-09-22 11:07:20 +03:00
Péter Szilágyi
83f3fc2e80 core/state/snapshot: be very noisy if the generator hits a trie error (#28178) 2023-09-22 10:27:58 +03:00
rjl493456442
03c2176a1d trie/triedb/pathdb: improve error log (#28177) 2023-09-22 09:33:17 +03:00
rjl493456442
4773dcbc81 trie: remove internal nodes between shortNode and child in path mode (#28163)
* trie: remove internal nodes between shortNode and child in path mode

* trie: address comments

* core/rawdb, trie: address comments

* core/rawdb: delete unused func

* trie: change comments

* trie: add missing tests

* trie: fix lint
2023-09-22 09:31:10 +03:00
Delweng
545f4c5547 core/rawdb: no need to run truncateFile for readonly mode (#28145)
Avoid truncating files, if ancients are opened in readonly mode. With this change, we return error instead of trying (and failing)  to repair
2023-09-21 04:05:55 -04:00
Delweng
5b9cbe30f8 cmd/clef: suppress fsnotify error if keydir not exists (#28160)
As the keydir will be automatically created after an account is created, no error message if the watcher is failed.
2023-09-20 06:39:46 -04:00
phenix3443
5c6f4b9f0d cmd/utils: fix typo in comment (#28159) 2023-09-19 21:20:18 +02:00
Guillaume Ballet
7ed5bc021a trie: add getter for preimage store in trie.Database (#28155) 2023-09-19 08:47:24 -04:00
Martin Holst Swende
30d5d7c1b3 go.mod: use existing version of karalabe/usb (#28127)
There is no 0.0.3 release of karalabe/usb.
2023-09-19 14:20:06 +02:00
Delweng
41a0ad9f03 cmd/devp2p: use bootnodes as crawl input (#28139)
This PR makes the tool use the --bootnodes list as the input to devp2p crawl.
The flag will take effect if the input/output.json file is missing or empty.
2023-09-19 14:18:29 +02:00
bnovil
4b748b7a27 eth: fix typo in comment (#28146) 2023-09-19 14:14:36 +02:00
Delweng
ef76afad35 core/rawdb: fix typo in comment (#28140) 2023-09-19 13:43:37 +02:00
Felix Lange
e9f78db79d cmd/evm: fix some issues with the evm run command (#28109)
* cmd/evm: improve flags handling

This fixes some issues with flags in cmd/evm. The supported flags did not
actually show up in help output because they weren't categorized. I'm also
adding the VM-related flags to the run command here so they can be given
after the subcommand name. So it can be run like this now:

   ./evm run --code 6001 --debug

* cmd/evm: enable all forks by default in run command

The default genesis was just empty with no forks at all, which is annoying because
contracts will be relying on opcodes introduced in a fork. So this changes the default to
have all forks enabled.

* core/asm: fix some issues in the assembler

This fixes minor bugs in the old assembler:

- It is now possible to have comments on the same line as an instruction.
- Errors for invalid numbers in the jump instruction are reported better
- Line numbers in errors were off by one
2023-09-19 13:41:16 +02:00
Péter Szilágyi
90d5bd85bc params: begin Geth v1.13.2 release cycle 2023-09-17 17:55:46 +03:00
Péter Szilágyi
3f40e65c48 params: release Geth v1.13.1 2023-09-17 17:54:33 +03:00
rjl493456442
c53b0fef2a core, eth/downloader: fix genesis state missing due to state sync (#28124)
* core: fix chain repair corner case in path-based scheme

* eth/downloader: disable trie database whenever state sync is launched
2023-09-17 17:35:09 +03:00
phenix3443
d8a351b58f params: fix typo in comment (#28129)
fix: typo
2023-09-17 17:02:48 +03:00
phenix3443
52234eb172 internal/flags: fix typo (#28133)
fix(flag): one typo
2023-09-17 17:02:11 +03:00
cam-schultz
217719347d internal/ethapi: correctly calculate effective gas price (#28130)
correctly calculate effective gas price
2023-09-17 17:00:04 +03:00
rjl493456442
9a9db3d265 eth/catalyst: fix engine API (#28135) 2023-09-17 16:50:18 +03:00
Péter Szilágyi
16cd1a7561 cmd/geth, internal/flags: print envvar config source and bad names (#28119) 2023-09-15 15:52:53 +03:00
Péter Szilágyi
4fa3db49a1 eth/downloader: prevent pivot moves after state commit (#28126) 2023-09-15 15:06:25 +03:00
Darioush Jalali
48fdb79de5 core/state: check err for iter.Error in fastDeleteStorage (#28122)
core/state: check err for iter.Error
2023-09-15 14:09:07 +08:00
Péter Szilágyi
65a17c00c7 metrics: add support for enabling metrics from env vars (#28118) 2023-09-14 13:56:06 +03:00
Felix Lange
909dd4a109 rlp/rlpgen: remove build tag (#28106)
* rlp/rlpgen: remove build tag

This tag was supposed to prevent unstable output when types reference each other. Imagine
there are two struct types A and B, where a reference to type B is in A. If I run rlpgen
on type B first, and then on type A, the generator will see the B.EncodeRLP method and
call it. However, if I run rlpgen on type A first, it will inline the encoding of B.

The solution I chose for the initial release of rlpgen was to just ignore methods
generated by rlpgen using a build tag. But there is a problem with this: if any code in
the package calls EncodeRLP explicitly, the package can't be loaded without errors anymore
in rlpgen, because the loader ignores it. Would be nice if there was a way to just make it
ignore invalid functions during type checking (they're not necessary for rlpgen), but
golang.org/x/tools/go/packages does not provide a way of ignoring them.

Luckily, the types we use rlpgen with do not reference each other right now, so we can
just remove the build tags for now.
2023-09-14 12:28:40 +02:00
Péter Szilágyi
ee654626ad internal/flags: fix loading env vars for custom flags (#28117) 2023-09-14 12:43:58 +03:00
Delweng
8514d665ee graphql: add 4844 blob fields (#27963)
This adds block and receipt fields for EIP-4844.

---------

Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-09-14 10:23:16 +02:00
Péter Szilágyi
86bc2cdf33 internal/flags: fix linter 2023-09-14 10:58:13 +03:00
Marius Kjærstad
636c64caa9 build: upgrade -dlgo version to Go 1.21.1 (#28113) 2023-09-14 10:34:52 +03:00
Péter Szilágyi
d9fbb71d63 cmd/geth, internal/flags, go.mod: colorize cli help, support env vars (#28103)
* cmd/geth, internal/flags, go.mod: colorize cli help, support env vars

* internal/flags: use stdout, not stderr for terminal detection
2023-09-14 10:33:59 +03:00
Sina Mahmoodi
b9b99a12e5 eth: abort on api operations not available in pbss-mode (#28104)
eth: abort on api calls not supporting pbss
2023-09-14 03:10:37 -04:00
Péter Szilágyi
eb7438997b cmd/geth: rename the protocols field in the metrics gague (#28102) 2023-09-13 13:17:55 -04:00
Martin Holst Swende
8b6cf128af metrics: refactor metrics (#28035)
This change includes a lot of things, listed below. 

### Split up interfaces, write vs read

The interfaces have been split up into one write-interface and one read-interface, with `Snapshot` being the gateway from write to read. This simplifies the semantics _a lot_. 

Example of splitting up an interface into one readonly 'snapshot' part, and one updatable writeonly part: 

```golang
type MeterSnapshot interface {
	Count() int64
	Rate1() float64
	Rate5() float64
	Rate15() float64
	RateMean() float64
}

// Meters count events to produce exponentially-weighted moving average rates
// at one-, five-, and fifteen-minutes and a mean rate.
type Meter interface {
	Mark(int64)
	Snapshot() MeterSnapshot
	Stop()
}
```

### A note about concurrency

This PR makes the concurrency model clearer. We have actual meters and snapshot of meters. The `meter` is the thing which can be accessed from the registry, and updates can be made to it. 

- For all `meters`, (`Gauge`, `Timer` etc), it is assumed that they are accessed by different threads, making updates. Therefore, all `meters` update-methods (`Inc`, `Add`, `Update`, `Clear` etc) need to be concurrency-safe. 
- All `meters` have a `Snapshot()` method. This method is _usually_ called from one thread, a backend-exporter. But it's fully possible to have several exporters simultaneously: therefore this method should also be concurrency-safe. 

TLDR: `meter`s are accessible via registry, all their methods must be concurrency-safe. 

For all `Snapshot`s, it is assumed that an individual exporter-thread has obtained a `meter` from the registry, and called the `Snapshot` method to obtain a readonly snapshot. This snapshot is _not_ guaranteed to be concurrency-safe. There's no need for a snapshot to be concurrency-safe, since exporters should not share snapshots. 

Note, though: that by happenstance a lot of the snapshots _are_ concurrency-safe, being unmutable minimal representations of a value. Only the more complex ones are _not_ threadsafe, those that lazily calculate things like `Variance()`, `Mean()`.

Example of how a background exporter typically works, obtaining the snapshot and sequentially accessing the non-threadsafe methods in it: 
```golang
		ms := metric.Snapshot()
                ...
		fields := map[string]interface{}{
			"count":    ms.Count(),
			"max":      ms.Max(),
			"mean":     ms.Mean(),
			"min":      ms.Min(),
			"stddev":   ms.StdDev(),
			"variance": ms.Variance(),
```

TLDR: `snapshots` are not guaranteed to be concurrency-safe (but often are).

### Sample changes

I also changed the `Sample` type: previously, it iterated the samples fully every time `Mean()`,`Sum()`, `Min()` or `Max()` was invoked. Since we now have readonly base data, we can just iterate it once, in the constructor, and set all four values at once. 

The same thing has been done for runtimehistogram. 

### ResettingTimer API

Back when ResettingTImer was implemented, as part of https://github.com/ethereum/go-ethereum/pull/15910, Anton implemented a `Percentiles` on the new type. However, the method did not conform to the other existing types which also had a `Percentiles`. 

1. The existing ones, on input, took `0.5` to mean `50%`. Anton used `50` to mean `50%`. 
2. The existing ones returned `float64` outputs, thus interpolating between values. A value-set of `0, 10`, at `50%` would return `5`, whereas Anton's would return either `0` or `10`. 

This PR removes the 'new' version, and uses only the 'legacy' percentiles, also for the ResettingTimer type. 

The resetting timer snapshot was also defined so that it would expose the internal values. This has been removed, and getters for `Max, Min, Mean` have been added instead. 

### Unexport types

A lot of types were exported, but do not need to be. This PR unexports quite a lot of them.
2023-09-13 13:13:47 -04:00
Péter Szilágyi
8d38b1fe62 core/rawdb: skip pathdb state inspection in hashdb mode (#28108) 2023-09-13 15:13:10 +03:00
Martin Holst Swende
43df612268 internal, log: remove code for old unsupported go-versions (#28090) 2023-09-13 01:42:32 -04:00
Péter Szilágyi
766272ff8c params: begin v1.13.1 release cycle 2023-09-12 14:03:50 +03:00
Péter Szilágyi
7371b38171 params: release Geth v1.13.0 2023-09-12 13:57:10 +03:00
Bala Murali Krishna Komatireddy
12ef276a7d consensus/misc: fix min gas limit error message (#28085) 2023-09-11 04:57:22 -04:00
lightclient
1efd12f695 core: fix calculation of blob gasprice in tx receipt (#28082)
This fixes the derived value BlobGasPrice on the receipt of EIP-4844 transactions, which was previously erroneously set to the price cap.
2023-09-11 02:14:20 -04:00
Martin Holst Swende
5cf53f51ac ethclient: use 'input', not 'data' as field for transaction input (#28078) 2023-09-08 18:33:36 +02:00
Péter Szilágyi
83886e40b6 go.mod: pull in a fix from pebble crl-release-23.1 (#28081) 2023-09-08 17:23:57 +03:00
rjl493456442
a7842c9cae core, trie: cleanup trie database (#28062) 2023-09-07 21:17:14 +08:00
Martin Holst Swende
a8d7201ec5 log: avoid stack lookups when not needed/used (#28069)
Avoids the somewhat expensive stack.Caller invocation by checking if it is needed
2023-09-07 08:48:49 -04:00
Martin Holst Swende
c60f7dd08d deps: update minisign (#28066)
This updates minisign to the latest version. One new thing is that minisign (not go-minisign) has started to prehash the file, and in order to make geth pass the version-check, we need to sign the file in legacy-mode.
2023-09-07 04:18:46 -04:00
Delweng
2e02c1ffd9 core/rawdb: don't warn for missing "unclean shutdown markers" (#28014)
This changes removes the warn-printout about not finding unclean shutdown markers, which always happens on fresh installs / wiped databases.
2023-09-06 06:29:51 -04:00
ucwong
2f77299136 go.mod: goupnp 1.3.0 (#28053) 2023-09-06 11:17:36 +03:00
lightclient
25733a4aad params: update 4844 parameters (#28026)
On ACD 163, it was agreed to bump the target and max blob values from `2/4` to `3/6` for future devnets until we could decide on final mainnet number. This change contains said update, making master pass all the hive tests. The final decision for mainnet cancun is still to be made.
---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-09-05 04:49:51 -04:00
lightclient
eff7c3bda0 core/forkid: skip genesis forks by time (#28034)
* core/forkid: skip genesis forks by time

* core/forkid: add comment about skipping non-zero fork times

* core/forkid: skip all time based forks in genesis using loop

* core/forkid: simplify logic for dropping time-based forks
2023-09-04 09:32:14 -04:00
lightclient
f260a9edb9 beacon/engine: add shouldOverrideBuilder to payload envelope (#28029)
beacon/engine: add shouldOverrideBuilder to payload envelope
2023-09-04 09:26:13 -04:00
Marius van der Wijden
28857080d7 eth/catalyst: set random value in dev mode (#27940)
* eth/catalyst: set random

* Apply suggestions from code review

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-31 14:37:16 -04:00
rjl493456442
0acc0a1f86 core/state: simplify storage trie update and commit (#28030)
This change improves function description and simplifies logic in statedb update and commit operations.
2023-08-31 14:33:18 -04:00
Jorge
53f3c2ae65 metrics, cmd/geth: informational metrics (prometheus, influxdb, opentsb) (#24877)
This chang creates a GaugeInfo metrics type for registering informational (textual) metrics, e.g. geth version number. It also improves the testing for backend-exporters, and uses a shared subpackage in 'internal' to provide sample datasets and ordered registry. 

Implements #21783

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-31 13:37:17 -04:00
Péter Szilágyi
5b159498bb go.mod: regenerate all indirect dependencies to clean up the junk (#28037) 2023-08-31 16:00:31 +03:00
lightclient
41ee96fdfe core/txpool/blobpool: fix rlp decoding flaw during offload (#28027) 2023-08-30 03:28:03 -04:00
Martin Holst Swende
b8adb4cb0c tests: use 'sender' in state tests if present (#28023)
A while back, statetests started coming with sender baked in, which at least 
evmone makes use of. Let's make use of that too, and save some cycles.
2023-08-29 04:36:10 +02:00
CrashOverride
fe24d22a62 miner/stress/clique: fix typo (#28016)
fix typo
2023-08-28 02:36:11 -04:00
Marius van der Wijden
f174ddba7a build, tests: add execution-spec-tests (#26985)
This makes it possible to run the execution-spec-tests (a.k.a. pyspec) in CI.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-26 15:42:27 +02:00
Martin Holst Swende
d4e345c7d4 core/state: fix missing import (#28010) 2023-08-26 04:43:36 -04:00
lightclient
3a662d4735 eth: remove check for tdd reached on pos api block tags (#27799)
This change defers to the blockchain for in what circumstances to return error, instead of handling many error-cases in the api backend.
2023-08-26 04:19:01 -04:00
rjl493456442
3ff6b3c31e core/state: implement fast storage deletion (#27955)
This changes implements faster post-selfdestruct iteration of storage slots for deletion, by using snapshot-storage+stacktrie to recover the trienodes to be deleted. This mechanism is only implemented for path-based schema. 

For hash-based schema, the entire post-selfdestruct storage iteration is skipped, with this change, since hash-based does not actually perform deletion anyway. 

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-26 04:13:22 -04:00
Shude Li
5ca7fb82d6 account/abi: handle solidity panic revert (#27868)
See  https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require
2023-08-26 04:10:48 -04:00
Martin Holst Swende
6aa88ccdd2 beacon/engine, eth/catalyst, miner: EIP-4788 CL/EL protocol updates (#27872)
This PR makes EIP-4788 work in the engine API and miner. It also fixes some bugs related to 
EIP-4844 block processing and mining. Changes in detail:

- Header.BeaconRoot has been renamed to ParentBeaconRoot.
- The engine API now implements forkchoiceUpdatedV3
- newPayloadV3 method has been updated with the parentBeaconBlockRoot parameter
- beacon root is now applied to new blocks in miner
- For EIP-4844, block creation now updates the blobGasUsed field of the header
2023-08-26 04:52:12 +02:00
Delweng
cde462c6bf eth/catalyst: reset to current header if chain is rewound (in dev mode) (#27992)
Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
2023-08-25 15:38:27 -04:00
Felix Lange
9bbb9df185 core/types: transaction and receipt encoding/decoding optimizations (#27976)
Just some minor optimizations I figured out a while ago. By using ReadBytes instead of
Bytes on the rlp stream, we can save the allocation of a temporary buffer for the typed tx
payload.

If kind == rlp.Byte, the size reported by Stream.Kind will be zero, but we need a buffer
of size 1 for ReadBytes. Since typed txs always have to be longer than 1 byte, we can just
return an error for kind == rlp.Byte.

There is a also a small change for Log: since the first three fields of Log are the ones that 
should appear in the canon encoding, we can simply ignore the remaining fields via 
struct tag. Doing this removes an indirection through the rlpLog type.

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-25 20:03:41 +02:00
Péter Szilágyi
6b98d18789 cmd, core, params: add support for the Holesky testnet (#28007)
* cmd, core, params: add support for the Holesky testnet

* cmd/devp2p: add support for holesky for the dns crawler
2023-08-25 18:11:40 +03:00
Péter Szilágyi
5e0eb62a8e eth/protocols/eth: stop advertising eth/66 for pathdb nodes (#28006) 2023-08-25 18:10:30 +03:00
Felix Lange
6dc9cdf15b core: support null balance in genesis (#28005) 2023-08-25 15:59:40 +02:00
aaronbuchwald
56d2366699 core/state/snapshot: replace diffToDisk ideal batch size with 64MB (#27977) 2023-08-25 15:48:10 +03:00
Guido Vranken
0ba2d3cfa4 core/vm/runtime: Add Random field to config (#28001) 2023-08-25 04:05:33 -04:00
rjl493456442
1a2135044c eth/catalyst: use block as finalization (#28000) 2023-08-24 11:49:13 +03:00
Delweng
45b198dd3a eth/catalyst: disable heartbeat for simulated beacon node (#27979)
* eth/catalyst: disable heartbeat for simulated beacon node

Signed-off-by: jsvisa <delweng@gmail.com>

* eth/catalyst: update

* eth/catalyst: disable heartbeat for tester

---------

Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-08-24 11:48:09 +03:00
Felix Lange
9b46986edc all: use rlp.DecodeBytes instead of rlp.Decode where possible (#27994) 2023-08-24 11:47:42 +03:00
Marius van der Wijden
60ec41ce73 miner: refactor getSealingBlock method (#27993) 2023-08-24 00:28:38 +02:00
lightclient
feb8f416ac miner: add to build block with EIP-4844 blobs (#27875)
---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-23 23:16:14 +02:00
Felix Lange
d1f6735171 core/rawdb: fix 32bit build (#27995) 2023-08-23 23:14:36 +02:00
Martin Holst Swende
eb6cbe37e1 core/state: remove public method ForEachStorage (#27986)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-23 21:53:31 +02:00
Marius van der Wijden
2f4dbb4f90 core/rawdb: allocate database keys with explicit size to avoid slice growth (#27772) 2023-08-23 21:41:56 +02:00
cui
4abc412348 crypto/bn256: eliminate dead store (#27944) 2023-08-23 21:26:30 +02:00
ucwong
e3f3e01504 les: use new atomic types (#27856)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-23 21:19:04 +02:00
Martin Holst Swende
f0f8703bf2 core/rawdb, ethdb/pebble: avoid fsync db in tests (#27836)
Adds an option to disable fsync for database operations.
This is to make tests faster.
2023-08-23 20:43:55 +02:00
Felix Lange
5c7136adb4 rlp: remove allocation of bytes.Reader in DecodeBytes (#27987) 2023-08-23 20:31:05 +02:00
Péter Szilágyi
52219ced8b travis: get rid of old useless GO111MODULE directives (#27991) 2023-08-23 18:54:30 +03:00
Shude Li
76d4ac1acb account/abi: convert if-else-if chain to tagged switch (#27869)
account/abi: conver if-else-if chain to tagged switch
2023-08-23 09:53:38 -04:00
Martin Holst Swende
4af98d4ee6 travis: increase travis wait time (#27975) 2023-08-23 16:49:36 +03:00
Péter Szilágyi
00fead91c4 cmd/utils: fix a startup issue on deleted chaindata but dangling ancients (#27989) 2023-08-23 16:42:37 +03:00
rjl493456442
bce5c46739 eth/catalyst: disable full payload when not in dev mode (#27921)
eth/catalyst: only enable full payload in dev mode
2023-08-23 15:14:04 +03:00
Péter Szilágyi
0c6bbeb423 core, eth, trie: expose more detailed dirty ram tracking for diff layers (#27971) 2023-08-23 14:08:39 +03:00
Péter Szilágyi
ab3762b2d9 go.mod: update pebble to crl-release-23.1 (#27967) 2023-08-23 10:50:28 +03:00
Delweng
c31f9cf23a graphql: fix nil deref on a timer (#27978)
graphql: fix the panic of nil timer.Stop

Signed-off-by: jsvisa <delweng@gmail.com>
2023-08-23 03:47:42 -04:00
Martin Holst Swende
16946d218a rpc: use go-winio for named pipes (#27972)
We're trying a new named pipe library, which should hopefully fix some occasional failures in CI.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-23 04:39:01 +02:00
Felix Lange
4c7053baf1 core: add BeaconRoot to header in GenerateChain (#27974)
Fixes an error in tests of internal/ethapi.
2023-08-22 18:29:17 +02:00
Martin Holst Swende
8d2492982b cmd/evm: add back stateroot to jsonl-output (#27968)
The PR #26274 broke the evm statetest command a bit, in that it stopped spitting out the stateroot following a non-successful statetest-execution. 

This PR changes it back, so the stateroot is unconditionally output on stderr, and makes it so fuzzing works again.
2023-08-22 09:37:04 -04:00
Martin Holst Swende
b8d38e76ef core, params, beacon/engine: implement EIP 4788 BeaconRoot (#27849)
This change implements "EIP 4788 : Beacon block root in the EVM". It implements version-2 of EPI-4788, main difference being that the contract is an actual contract rather than a precompile, as in #27289.
2023-08-22 08:33:39 -04:00
Marius van der Wijden
0b4b299099 go.mod: update docker (#27970) 2023-08-22 14:11:25 +03:00
Martin Holst Swende
55c5f5964d travis, build: update Go to 1.21.0 (#27958)
build: update to go 1.21
2023-08-22 11:00:01 +03:00
shuo
bbee0e7e50 miner: fix reply -> replay typo (#27961)
* typo: reply -> replay

* rebuild
2023-08-22 10:59:38 +03:00
Delweng
7c0d90c8c9 core: ensure txindex will be triggered at least once (#27847)
Currently, we trigger the logic to (un)index transactions when the node receives a new
block. However, in some cases the node may not receive new blocks (eg, when the Geth node
is configured without peer discovery, or when it acts as an RPC node for historical-only
data).

In these situations, the Geth node user may not have previously configured txlookuplimit
(i.e. the default of around one year), but later realizes they need to index all
historical blocks. However, adding txlookuplimit=0 and restarting geth has no effect. This
change makes it check for required indexing work once, on startup, to fix the issue.

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-22 02:58:20 +02:00
Delweng
9f4a528793 internal/ethapi: add testcases for blobTx (#27818)
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-22 02:53:29 +02:00
jwasinger
f56ee7d9c5 eth/catalyst: set finalized block hash properly in dev mode (#27886)
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-21 13:33:37 -04:00
Marius van der Wijden
b3024e8fe6 eth: ignore genesis block on importChain (#27956) 2023-08-21 13:32:34 -04:00
Marius van der Wijden
5976e58415 trie: reduce allocs in recHash (#27770) 2023-08-18 22:41:19 +02:00
Marius van der Wijden
7dea9c10cd internal/ethapi: eth API changes needed for 4844 (#27928)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-18 14:22:35 +02:00
Roberto Bayardo
950ccddfc8 internal/ethapi: optimize & clean up EstimateGas (#27710)
Optimizations:

- Previously, if a transaction was reverting, EstimateGas would exhibit worst-case behavior and binary search up to the max gas limit (~40 state-clone + tx executions). This change allows EstimateGas to return after only a single unconstrained execution in this scenario.
- Uses the gas used from the unconstrained execution to bias the remaining binary search towards the likely solution in a simple way that doesn't impact the worst case. For a typical contract-invoking transaction, this reduces the median number of state-clone+executions from 25 to 18 (28% reduction).

Cleanup:

- added & improved function + code comments
- correct the EstimateGas documentation to clarify the gas limit determination is at latest block, not pending, if the blockNr is unspecified.
2023-08-18 03:03:14 -04:00
Delweng
649deb69f3 eth/downloader: fix rare crash when parent header missing in db (#27945)
ReadSkeletonHeader can return nil if the header is missing, so we should
not access fields on it. Note that calling .Hash() on a nil header is fine, so there 
is no need to actually check for nil.

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-17 23:15:29 +02:00
Martin Holst Swende
1aa5520d75 core/txpool/legacypool: protect cache with mutex (#27898)
This change fixes the a potential race by using mutexes when the m.cache is read or modified.
2023-08-17 05:22:18 -04:00
lightclient
32fde3f838 core/forkid: correctly compute forkid when timestamp fork is activated in genesis (#27895)
This changes the forkID calculation to ignore time-based forks that occurred before the
genesis block. It's supposed to be done this way because the spec says:

> If a chain is configured to start with a non-Frontier ruleset already in its genesis, that is NOT considered a fork.
2023-08-16 23:31:02 +02:00
lightclient
a3e35414b7 core/types: fix unmarshalling of BlobTx values (#27939)
FromBig returns true *when overflow occurs*
2023-08-16 23:22:15 +02:00
Delweng
386cba15b5 node: increase batch limits for auth rpc API (#27924)
This raises the JSON-RPC batch request limits significantly for the engine API endpoint.
The limits are now also hard-coded, so users won't get them wrong. I have chosen these limits:

    maximum batch items: 2000
    maximum batch response size: 250MB

While it would also be possible to disable batch limits completely for the engine API, 
I think having some limits is a good safety net against misbehaving CLs. Since this
 isn't configurable, we really want to ensure this limit will never become an issue in the
 CL/EL communication, so I set them quite high.

---------

Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-16 15:26:49 +02:00
Martin Holst Swende
a16d757cd4 build: remove ubuntu kinetic (deprecated) (#27933) 2023-08-16 12:11:22 +02:00
Joe Netti
e0b119884c eth/tracers/js: use t.toBig on ctx.GasPrice for js tracing (#27903)
This change fixes a bug in js tracer, where `ctx.GasPrice.toString(16)` returns a number string in base `10`.
2023-08-15 14:19:37 -04:00
Paweł Bylica
ab28680e66 trie: add tests for "short" nodes in StackTrie (#27932) 2023-08-15 14:16:00 -04:00
lonika
05a8b887a9 crypto/bls12381: fix typo in comment (#27930) 2023-08-15 14:37:34 +02:00
Delweng
f1801a9fed internal/ethapi: implement eth_getBlockReceipts (#27702) 2023-08-15 14:35:48 +02:00
ucwong
509cd428e9 go.mod: upgrade goja (#27899) 2023-08-14 14:59:05 +02:00
Delweng
68855216c9 cmd/utils: restore support for txlookuplimit flag (#27917)
This fixes a regression where -txlookuplimit was not applied anymore.
2023-08-14 14:58:01 +02:00
Felix Lange
2a6beb6a39 core/types: support for optional blob sidecar in BlobTx (#27841)
This PR removes the newly added txpool.Transaction wrapper type, and instead adds a way
of keeping the blob sidecar within types.Transaction. It's better this way because most
code in go-ethereum does not care about blob transactions, and probably never will. This
will start mattering especially on the client side of RPC, where all APIs are based on
types.Transaction. Users need to be able to use the same signing flows they already
have.

However, since blobs are only allowed in some places but not others, we will now need to
add checks to avoid creating invalid blocks. I'm still trying to figure out the best place
to do some of these. The way I have it currently is as follows:

- In block validation (import), txs are verified not to have a blob sidecar.
- In miner, we strip off the sidecar when committing the transaction into the block.
- In TxPool validation, txs must have a sidecar to be added into the blobpool.
  - Note there is a special case here: when transactions are re-added because of a chain
    reorg, we cannot use the transactions gathered from the old chain blocks as-is,
    because they will be missing their blobs. This was previously handled by storing the
    blobs into the 'blobpool limbo'. The code has now changed to store the full
    transaction in the limbo instead, but it might be confusing for code readers why we're
    not simply adding the types.Transaction we already have.

Code changes summary:

- txpool.Transaction removed and all uses replaced by types.Transaction again
- blobpool now stores types.Transaction instead of defining its own blobTx format for storage
- the blobpool limbo now stores types.Transaction instead of storing only the blobs
- checks to validate the presence/absence of the blob sidecar added in certain critical places
2023-08-14 10:13:34 +02:00
Felix Lange
68860063fb internal/build: apply -ubuntu to env (#27910) 2023-08-12 10:32:50 +02:00
Felix Lange
e91b21ce2b go.mod, build: upgrade c-kzg-4844 (#27907)
This upgrades to the latest release of ckzg, and also attempts to fix some blst-related
build errors that occur on launchpad.net.
2023-08-12 00:21:46 +02:00
Péter Szilágyi
be65b47645 all: update golang/x/ext and fix slice sorting fallout (#27909)
The Go authors updated golang/x/ext to change the function signature of the slices sort method. 
It's an entire shitshow now because x/ext is not tagged, so everyone's codebase just 
picked a new version that some other dep depends on, causing our code to fail building.

This PR updates the dep on our code too and does all the refactorings to follow upstream...
2023-08-12 00:04:12 +02:00
Péter Szilágyi
0ce331f56a trie/triedb/pathdb: make shutdown journal log friendlier (#27905) 2023-08-11 17:05:35 +03:00
DongXi Huang
80b76a9527 core/types: remove duplication in eip2930 signer (#27860)
Remove duplication in signer
---------

Co-authored-by: GDdark <huangdongxi@minijoy.work>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-11 09:50:57 -04:00
Felix Lange
8f8ef2bc0c rpc: attempt to fix ping/pong logic race (#27733)
This should fix #27726. With enough load, it might happen that the SetPongHandler 
callback gets invoked before the call to SetReadDeadline is made in pingLoop. When 
this occurs, the socket will end up with a 30s read deadline even though it got the pong,
which will lead to a timeout.

The fix here is processing the pong on pingLoop, synchronizing with the code that 
sends the ping.
2023-08-11 15:16:45 +02:00
Delweng
35f7f3d015 ethdb/leveldb: support more than 7 levels in metrics (#27904) 2023-08-11 15:15:49 +02:00
imulmat4
6ddb92cac3 core/txpool/blobpool: fix metrics name for prometheus export (#27901) 2023-08-11 10:12:26 +03:00
Péter Szilágyi
e2507a17e8 params: switch release family to 1.13 to prep for PBSS 2023-08-10 22:22:17 +03:00
rjl493456442
503f1f7ada all: activate pbss as experimental feature (#26274)
* all: activate pbss

* core/rawdb: fix compilation error

* cma, core, eth, les, trie: address comments

* cmd, core, eth, trie: polish code

* core, cmd, eth: address comments

* cmd, core, eth, les, light, tests: address comment

* cmd/utils: shorten log message

* trie/triedb/pathdb: limit node buffer size to 1gb

* cmd/utils: fix opening non-existing db

* cmd/utils: rename flag name

* cmd, core: group chain history flags and fix tests

* core, eth, trie: fix memory leak in snapshot generation

* cmd, eth, internal: deprecate flags

* all: enable state tests for pathdb, fixes

* cmd, core: polish code

* trie/triedb/pathdb: limit the node buffer size to 256mb

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-08-10 22:21:36 +03:00
Sina Mahmoodi
5e89ff4d6b graphql: validate block params (#27876)
Block takes a number and a hash. The spec is unclear on what should happen in this case, leaving it an implemenation detail. With this change, we return an error in case both number and hash are passed in.
2023-08-10 07:00:52 -04:00
dependabot[bot]
86d7f5aeee deps: update supranational/blst to 0.3.11 (#27890)
build(deps): bump github.com/supranational/blst

Bumps [github.com/supranational/blst](https://github.com/supranational/blst) from 0.3.11-0.20230406105308-e9dfc5ee724b to 0.3.11.
- [Release notes](https://github.com/supranational/blst/releases)
- [Commits](https://github.com/supranational/blst/commits/v0.3.11)

---
updated-dependencies:
- dependency-name: github.com/supranational/blst
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-10 06:50:09 -04:00
Martin Holst Swende
8d1db1601d eth/filters, core/rawdb: remove unused param, refactor filtering-loop (#27891)
This change removes a chainconfig parameter passed into rawdb.ReadLogs, which is not used nor needed.
It also modifies the filter loop slightly, avoiding a labeled break and instead using a method.

This change does not modify any behaviour.
2023-08-10 06:49:05 -04:00
Felix Lange
d9a8b0ff71 params: begin v1.12.2 release cycle 2023-08-10 12:13:15 +02:00
Felix Lange
9c216bd6cb params: release go-ethereum v1.12.1 2023-08-10 12:10:33 +02:00
Guillaume Ballet
67979022aa core/state: move UpdateContractCode before the trie hash is computed (#27853)
Context: The UpdateContractCode method was introduced for the state storage commitment
schemes that include the whole code for their commitment computation. It must therefore be called
before the root hash is computed at the end of IntermediateRoot.

This should have no impact on the MPT since, in this context, the method is a no-op.
2023-08-09 18:02:45 +02:00
Delweng
10d9f9377b graphql: add yParity field for transactions (#27882)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-09 17:57:57 +02:00
Felix Lange
7ec60d5f0c p2p: move ping handling into pingLoop goroutine (#27887)
Moving the response sending there allows tracking all peer goroutines
in the peer WaitGroup.
2023-08-09 16:00:31 +02:00
Martin Holst Swende
e13fa32cea core/vm: update 4844 - point evaluation precompile address (#27874) 2023-08-08 15:54:19 +03:00
Martin Holst Swende
0d772b9f09 graphql: avoid greedy allocation (#27873)
Fixes a graphql-dos

---------

Co-authored-by: Sina Mahmoodi <1591639+s1na@users.noreply.github.com>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-08-08 07:35:58 -04:00
ucwong
6d2bcb911a p2p/simulations/examples: use atomic.Int64 (#27861) 2023-08-07 18:30:05 +02:00
Amin Talebi
eeebb07c73 internal/ethapi: add state override to estimateGas (#27845) 2023-08-07 16:03:57 +02:00
ucwong
d14c07d91e accounts: use atomic type (#27857) 2023-08-07 03:11:50 -04:00
ucwong
857476753d internal: use atomic type (#27858) 2023-08-07 03:11:06 -04:00
Christopher Harrison
60070fe5c6 internal/ethapi, graphql: correct comments about gas price logic (#27752) 2023-08-05 01:08:53 +02:00
ucwong
5c30541c2a log: use atomic types (#27763)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-05 00:58:53 +02:00
Felix Lange
bb148dd342 core/types: support yParity field in JSON transactions (#27744)
This adds support for the "yParity" field in transaction objects returned by RPC
APIs. We somehow forgot to add this field even though it has been in the spec for
a long time.
2023-08-05 00:54:55 +02:00
Darioush Jalali
57cdbaef30 all: remove trailing whitespace (#27741) 2023-08-05 00:24:32 +02:00
Felix Lange
df544350bc core/types: fix immutability guarantees in Block (#27844)
This change rearranges the accessor methods in block.go and fixes some minor issues with
the copy-on-write logic of block data. Fixed issues:

- Block.WithWithdrawals did not create a shallow copy of the block.

- Block.WithBody copied the header unnecessarily, and did not preserve withdrawals.

However, the bugs did not affect any code in go-ethereum because blocks are *always*
created using NewBlockWithHeader().WithBody().WithWithdrawals()
2023-08-04 14:16:23 +02:00
Péter Szilágyi
6e934f40f9 eth/protocols/snap: fix batch writer when resuming an aborted sync (#27842) 2023-08-03 14:51:02 +03:00
Marius Kjærstad
8224bb9218 build: upgrade -dlgo version to Go 1.20.7 (#27835) 2023-08-02 12:53:05 +03:00
ucwong
d04bde0a20 p2p: use atomic types (#27764)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-01 23:20:52 +02:00
Delweng
ff97b4cc6a cmd/geth: disable automaxprocs log (#27814)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-08-01 18:02:36 +02:00
rjl493456442
7de748d3f6 all: implement path-based state scheme (#25963)
* all: implement path-based state scheme

* all: edits from review

* core/rawdb, trie/triedb/pathdb: review changes

* core, light, trie, eth, tests: reimplement pbss history

* core, trie/triedb/pathdb: track block number in state history

* trie/triedb/pathdb: add history documentation

* core, trie/triedb/pathdb: address comments from Peter's review

Important changes to list:

- Cache trie nodes by path in clean cache
- Remove root->id mappings when history is truncated

* trie/triedb/pathdb: fallback to disk if unexpect node in clean cache

* core/rawdb: fix tests

* trie/triedb/pathdb: rename metrics, change clean cache key

* trie/triedb: manage the clean cache inside of disk layer

* trie/triedb/pathdb: move journal function

* trie/triedb/path: fix tests

* trie/triedb/pathdb: fix journal

* trie/triedb/pathdb: fix history

* trie/triedb/pathdb: try to fix tests on windows

* core, trie: address comments

* trie/triedb/pathdb: fix test issues

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-01 15:17:32 +03:00
ucwong
9d744f0ca8 cmd/bootnode: fix timer leak (#27754) 2023-08-01 14:12:11 +02:00
Delweng
f404a2d0f1 cmd/evm: set ExcessBlobGas from env (#27796)
Sets the `currentExcessBlobGas` from env, alternatively calculates it based on `parentExcessBlobGas` and `parentBlobGasUsed`. It then emits the `currentExcessBlobGas` and `currentBlobGasUsed` into the output, to be used as parent-values for a future iteration. 

Closes #27785
Closes #27783

---------

Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-08-01 07:58:26 -04:00
Delweng
7c95ebd63d consensus/misc: move eip1559 into a package (#27828)
* consensus/misc: move eip1559 as a sub directory

Signed-off-by: jsvisa <delweng@gmail.com>

* consensus/misc: package name

Signed-off-by: jsvisa <delweng@gmail.com>

* all: eip1559

Signed-off-by: jsvisa <delweng@gmail.com>

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-08-01 12:58:45 +03:00
rjl493456442
2fd77a6a7e core/txpool/blobpool: remove error log when finalized block is nil (#27822)
* core/txpool/blobpool: remove error log when finalized block is nil

* core/txpool/blobpool: take peter's suggestion
2023-08-01 10:09:20 +03:00
Martin Holst Swende
852be575e1 tests: make tests pass on windows/386 (#27821)
* tests: split up state test execution

* Revert "tests: split up state test execution"

This reverts commit 96017c248c.

* build: bump test timeout to 20 minutes
2023-08-01 10:08:19 +03:00
Delweng
3ca92f70e5 all: replace data gas to blob gas in comments (#27825)
* eth: excessDataGas -> excessBlobGas

* consensus: data gas -> blob gas

* core: data gas -> blob gas

* params: data gas -> blob gas
2023-08-01 10:07:25 +03:00
Zig Blathazar
4e9775668e cmd/bootnode: defer udp connection close (#27787) 2023-07-31 13:15:13 -04:00
rjl493456442
817553cc28 core, trie: track state change set with account address (#27815) 2023-07-31 15:07:51 +03:00
Delweng
43a1a48ee2 core: remove pointless check for excessBlobGas nilness (#27797)
* core: check excessBlobGas in front

Signed-off-by: jsvisa <delweng@gmail.com>

* core: no need to manual panic

Signed-off-by: jsvisa <delweng@gmail.com>

* core: no comment

Signed-off-by: jsvisa <delweng@gmail.com>

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-07-31 10:54:26 +03:00
Shude Li
5a4eba6886 eth: conver if-else-if chain to tagged switch (#27816) 2023-07-31 10:22:36 +03:00
Shude Li
95cc7bf4f8 cmd/geth: import package catalyst once (#27803) 2023-07-31 08:18:13 +03:00
Mario Vega
8f2ae29b8f core/types: fix receipt blob fields marshaling (#27793) 2023-07-28 10:08:38 +03:00
Marius van der Wijden
d9556533c3 core/types: put header fields in correct order (#27791) 2023-07-27 17:15:08 +03:00
Péter Szilágyi
57268f7e6c all: rename dataGas to blobGas (#27789) 2023-07-27 16:53:28 +03:00
Péter Szilágyi
0f4b21feac core/txpool/blobpool: fix a merge conflict from a package rename (#27790) 2023-07-27 14:53:05 +03:00
Felix Lange
393d4db18c core/types: add 4844 data gas fields in Receipt (#27743)
* core/types: add data gas fields in Receipt

* core/types: use BlobGas method of tx

* core: fix test

* core/types: fix receipt tests, add data gas used field test

---------

Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-07-27 14:11:09 +03:00
Péter Szilágyi
1662228ac6 core/txpool/blobpool: 4844 blob transaction pool (#26940)
* core/blobpool: implement txpool for blob txs

* core/txpool: track address reservations to notice any weird bugs

* core/txpool/blobpool: add support for in-memory operation for tests

* core/txpool/blobpool: fix heap updating after SetGasTip if account is evicted

* core/txpool/blobpool: fix eviction order if cheap leading txs are included

* core/txpool/blobpool: add note as to why the eviction fields are not inited in reinject

* go.mod: pull in inmem billy form upstream

* core/txpool/blobpool: fix review commens

* core/txpool/blobpool: make heap and heap test deterministic

* core/txpool/blobpool: luv u linter

* core/txpool: limit blob transactions to 16 per account

* core/txpool/blobpool: fix rebase errors

* core/txpool/blobpool: luv you linter

* go.mod: revert some strange crypto package dep updates
2023-07-27 13:45:35 +03:00
Darioush Jalali
37b952a4a2 core/types: deepcopy ExcessDataGas, DataGasUsed (#27767) 2023-07-27 11:32:15 +03:00
Justin Traglia
2274a03e33 crypto/kzg4844: do lazy init in all ckzg funcs (#27679)
* crypto/kzg4844: remove unnecessary init call & fix typo

* Fix kzg4844 tests/benchmarks

* Make init lazy & revert changes to tests
2023-07-24 19:13:34 +03:00
ucwong
a196f3e8a2 cmd/devp2p: atomic types used (#27755) 2023-07-24 13:23:38 +03:00
ucwong
7a1fba1a02 cmd/geth: atomic types used (#27756) 2023-07-24 13:22:54 +03:00
rjl493456442
88f3d61468 all: expose block number information to statedb (#27753)
* core/state: clean up

* all: add block number infomration to statedb

* core, trie: rename blockNumber to block
2023-07-24 13:22:09 +03:00
Marius van der Wijden
a46f4173cd ethclient/gethclient: gofmt -s (#27762) 2023-07-24 13:21:26 +03:00
Pierre Grimaud
7f756dc118 cmd/evm/testdata: fix typos in docs (#27742) 2023-07-18 14:07:25 +02:00
Felix Lange
e86ad52640 beacon/engine, eth/catalyst: EIP-4844 updates for the engine API (#27736)
This is a spin-out from the EIP-4844 devnet branch, containing just the Engine API modifications
and nothing else. The newPayloadV3 endpoint won't really work in this version, but we need the
data structures for testing so I'd like to get this in early.

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2023-07-18 09:44:16 +02:00
Felföldi Zsolt
d4d88f9bce les: remove obsolete code related to PoW header syncing (#27737)
This change removes PoW header syncing related code from LES and also deletes 
duplicated packages les/catalyst, les/downloader and les/fetcher. These package copies
were created because people wanted to make changes in their eth/ counterparts, but weren't
able to adapt LES code to the API changes.
2023-07-17 20:48:11 +02:00
jwasinger
988d84aa7c core/state, core/vm: implement EIP 6780 (#27189)
EIP-6780: SELFDESTRUCT only in same transaction

>     SELFDESTRUCT will recover all funds to the caller but not delete the account, except when called in the same transaction as creation

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-07-17 13:02:18 -04:00
Martin Holst Swende
b058cf454b core, tests: EIP-4844 transaction processing logic (#27721)
This updates the reference tests to the latest version and also adds logic
to process EIP-4844 blob transactions into the state transition. We are now
passing most Cancun fork tests.

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-07-15 23:27:36 +02:00
ucwong
99e000cb13 core/vm: use types.EmptyCodeHash (#27729) 2023-07-15 17:45:57 +02:00
jwasinger
d233b6b23a core: replace instances of 'suicide' with 'selfdestruct' to improve code consistency. (#27716)
---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com>
2023-07-15 10:35:30 -04:00
Yurie
00408f7479 accounts/abi/bind/backends: fix goroutine leak in unit test (#27705) 2023-07-15 10:33:46 -04:00
Ömer Faruk Irmak
34d5072159 metrics: NilResettingTimer.Time should execute the timed function (#27724) 2023-07-14 19:19:03 +02:00
Delweng
47b9f1b4ae cmd/geth: use automaxprocs to apply cpu quota correctly (#27506)
It is usually best to set GOMAXPROCS to the number of available CPU cores. However, setting
it like that does not work well when the process is quota-limited to a certain number of CPUs.
The automaxprocs library configures GOMAXPROCS, taking such limits into account.
2023-07-14 19:14:47 +02:00
Ömer Faruk Irmak
13c0305106 metrics: NilTimer should still run the function to be timed (#27723) 2023-07-14 18:10:16 +02:00
Seungbae Yu
60ecf48dd4 cmd/bootnode, p2p: support for alternate mapped ports (#26359)
This changes the port mapping procedure such that, when the requested port is unavailable
an alternative port suggested by the router is used instead.

We now also repeatedly request the external IP from the router in order to catch any IP changes.

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-07-14 14:58:27 +02:00
ucwong
c40ab6af72 core/blockchain: fast to snap in comments (#27722) 2023-07-14 15:06:51 +03:00
ucwong
e1fe6bc846 go.sum: go mod tidy (#27717) 2023-07-13 16:34:29 +02:00
Ryan Schneider
517ac886d4 eth/tracers/native: panic on memory read in prestateTracer (#27691)
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-07-13 14:44:42 +02:00
Delweng
1e069cf802 eth/tracers: add ReturnData in the tracer's response (#27704)
The struct logger (or opcode tracer) was missing the return data field even
if this was explicitly enabled by user via `"enableReturnData": true` in the config.
This PR fixes this issue.

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-07-13 14:43:25 +02:00
Delweng
5d035043ea internal/ethapi: add more testcase for GetTransactionReceipt (#27527)
* internal/ethapi: testBackend reuse the same db

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: implment GetTransaction

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: implement GetReceipts

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: insert receipts and setup txlookup

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: add simple success tx receipt test

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: add case create contract

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: add contract call receipt

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: add tx notfound

Signed-off-by: jsvisa <delweng@gmail.com>

* internal/ethapi: add dynamic fee testcase

* internal/ethapi: add accessList receipt

* internal/ethapi: no need to insert receipt chain, no error

* internal/ethapi: use HeaderByHash instead

* internal/ethapi: add one more case

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-07-13 06:47:32 -04:00
Delweng
10a136a4f9 internal: early exit if tx for getTxReceipt not found (#27712)
internal/ethapi: fast exit if tx notfound
2023-07-13 06:42:48 -04:00
Sina Mahmoodi
4f0d8f0d15 graphql: fix race in withdrawals test (#27706)
graphql: fix race in test
2023-07-13 06:41:58 -04:00
Delweng
714f75943b eth, miner: rm redundant type declare (#27713)
* eth: rm redundant type from array, slice, or map

* miner: rm redundant type from array, slice, or map
2023-07-13 09:55:31 +03:00
Marius Kjærstad
040a4a543b build: upgrade -dlgo version to Go 1.20.6 (#27708) 2023-07-12 20:38:12 +03:00
cui fliter
80b7bfe70d accounts, cmd/evm: fix docstrings (#27703)
fix function name in comment

Signed-off-by: cui fliter <imcusg@gmail.com>
2023-07-12 06:01:55 -04:00
Felix Lange
a426999fc9 p2p/discover: filter bootnodes by netrestrict (#27701)
This prevents an issue where the node would attempt to contact the bootstrap
nodes even if they weren't contained in the netrestrict list.
2023-07-12 12:01:38 +02:00
rjl493456442
0b1f97e151 core/rawdb: support freezer batch read with no size limit (#27687)
This change adds the ability to perform reads from freezer without size limitation. This can be useful in cases where callers are certain that out-of-memory will not happen (e.g. reading only a few elements). 

The previous API was designed to behave both optimally and secure while servicing a request from a peer, whereas this change should _not_ be used when an untrusted peer can influence the query size.
2023-07-12 03:19:01 -04:00
Felix Lange
cecd22143b go.mod: upgrade github.com/karalabe/usb to fix build warning (#27698) 2023-07-11 22:34:22 +02:00
Mskxn
7a565fa4fe console: add cleanup to avoid leaks in newTester (#27695) 2023-07-11 21:27:48 +02:00
lightclient
645b0db98e cmd/utils, p2p: clean up discovery setup (#27518)
This simplifies the code that initializes the discovery a bit, and
adds new flags for enabling/disabling discv4 and discv5 separately.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-07-11 21:21:32 +02:00
rjl493456442
4b06e4f25e core/state: value diff tracking in StateDB (#27349)
This change makes the StateDB track the state key value diff of a block transition.
We already tracked current account and storage values for the purpose of updating
the state snapshot. With this PR, we now also track the original (pre-transition) values
of accounts and storage slots.
2023-07-11 15:43:23 +02:00
Delweng
aecf3f9579 internal/blocktest: add package for shared test code (#27270) 2023-07-11 14:57:02 +02:00
lightclient
e1fd3d67e5 eth: better active protocol handler tracking (#27665)
Fixes an issue where waitgroups were used erroneously, which could lead to waitgroup being added to while wait was already invoked.
2023-07-11 03:57:42 -04:00
Charles Cooper
5c9cbc218a core/vm: implement EIP-5656, mcopy instruction (#26181)
Implements [EIP 5656](https://eips.ethereum.org/EIPS/eip-5656), MCOPY instruction, and enables it for Cancun. 

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-07-11 03:55:34 -04:00
Martin Holst Swende
af8b138c1a core/vm: define cancun + enable 1153 (tstore/tload) in cancun (#27663) 2023-07-10 14:40:31 -04:00
jwasinger
c2db667c8f miner: remove unused commented code (#27664) 2023-07-07 11:14:24 +03:00
Martin Holst Swende
c866dfdc78 core: remove outdated tests (#27662)
Back before #27178 , we spun up a number of ethash verifiers to verify headers. So we also had tests to ensure that we were indeed able to abort verification even if we had multiple workers running.

With PR #27178, we removed the parallelism in verification, and these tests are now failing, since we now just sequentially fire away the results as fast as possible on one routine.

This change removes the (sometimes failing) tests
2023-07-06 12:05:34 -04:00
lightclient
cbf2579691 p2p, p2p/discover: add dial metrics (#27621)
This PR adds metrics for p2p dialing, which gives us visibility into the quality of the dial 
candidates  returned by our discovery methods.
2023-07-06 16:20:31 +02:00
jwasinger
ea782809f7 cmd/geth: implement dev mode for post-merge (#27327)
This change adds back the 'geth --dev' mode of operation, using a cl-mocker. 

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com>
2023-07-06 04:42:34 -04:00
John Chase
ab0e0f3517 signer/core: show helptext when clef rejects signing (#27538)
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-07-06 03:50:44 -04:00
Darioush Jalali
83d7f426d1 core: stop chain when tests are finished (#27660)
core (blockchain_test): add chain.Stop() to tests
2023-07-06 02:56:42 -04:00
Exca-DK
863f6dac19 ethdb/leveldb: update leveldb metrics collection (#27643)
This removes text parsing in leveldb metrics collection code. All metrics
can now be accessed through the stats API provided by leveldb.

We also add new gauge-typed metrics that count the number of tables at each level.

---------

Co-authored-by: Exca-DK <Exca-DK@users.noreply.github.com>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-07-06 00:04:07 +02:00
rjl493456442
59f7b289c3 cmd, core, eth, graphql, trie: no persisted clean trie cache file (#27525)
The clean trie cache is persisted periodically, therefore Geth can
quickly warmup the cache in next restart.

However it will reduce the robustness of system. The assumption is
held in Geth that if the parent trie node is present, then the entire
sub-trie associated with the parent are all prensent.

Imagine the scenario that Geth rewinds itself to a past block and
restart, but Geth finds the root node of "future state" in clean
cache then regard this state is present in disk, while is not in fact.

Another example is offline pruning tool. Whenever an offline pruning
is performed, the clean cache file has to be removed to aviod hitting
the root node of "deleted states" in clean cache.

All in all, compare with the minor performance gain, system robustness
is something we care more.
2023-07-04 10:21:06 +03:00
Curith
6ca3ef9a7b node: fix listening on IPv6 address (#27628) (#27635) 2023-07-02 13:21:16 +02:00
Guillaume Ballet
8bbb16b70e core/state, light, les: make signature of ContractCode hash-independent (#27209)
* core/state, light, les: make signature of ContractCode hash-independent

* push current state for feedback

* les: fix unit test

* core, les, light: fix les unittests

* core/state, trie, les, light: fix state iterator

* core, les: address comments

* les: fix lint

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-06-28 12:11:02 +03:00
Guillaume Ballet
85b8d1c06c params, trie: add verkle fork management + upgrade go-verkle (#27464)
* params, trie: add verkle fork management + upgrade go-verkle

* remove the two verkle files

* core, eth, params: add missing function

* Gary's feedback

* remove trie/utils/verkle.go

* add verkle block override

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-06-28 12:08:48 +03:00
Marius van der Wijden
f5d3d486e4 eth: send big transactions by announce/retrieve only (#27618)
* eth: send big transactions by announce/retrieve only

* Update eth/handler.go

Co-authored-by: Martin Holst Swende <martin@swende.se>

* eth: remove superfluous bracket

* eth: add whitespace

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-06-28 12:06:20 +03:00
hero5512
eed7983c7c core/txpool/legacypool: fix typo (#27620) 2023-06-27 20:28:18 +03:00
Guillaume Ballet
c7b099b2ea trie, core/state: revert error removal in (*state.Trie).Commit (#27544)
* trie, core/state: revert error removal in (*state.Trie).Commit

* Gary's nitpick :)

Co-Authored-By:  rjl493456442 <garyrong0905@gmail.com>

---------

Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
2023-06-27 15:36:38 +03:00
aaronbuchwald
d73eb87979 core: log message if DeriveFields returns error (#27530)
This error will never happen, but if it ever does happen, we will at least see it.
2023-06-27 10:29:19 +02:00
Sanghee Choi
900591299f common/lru: add test case for BasicLRU.Peek (#27559) 2023-06-27 10:27:40 +02:00
Marius van der Wijden
d7ea278fe3 core/vm: move TSTORE,TLOAD to correct opcode nums (#27613)
* core/vm: move TSTORE,TLOAD to correct opcode nums

* core/vm: cleanup
2023-06-27 03:25:08 -04:00
rjl493456442
4b90c4488d ethdb/pebble: use sync mode for pebble writes (#27615) 2023-06-27 03:19:02 -04:00
puhtaytow
b4bc9b0db6 cmd/geth: error message should not be capitalised (#27549)
error message should not be capitalized / consistency
2023-06-27 09:12:03 +03:00
Delweng
80441779d4 eth/protocols: put protocols in order (#27543)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-06-27 09:11:06 +03:00
Sanghee Choi
2754b197c9 common/math: fix typo in comment (#27561) 2023-06-25 17:33:50 +02:00
Francisco de Borja Aranda Castillejo
942ba4ddaa crypto/secp256k1: define NDEBUG only if not defined (#27550) 2023-06-23 19:02:05 +02:00
Guillaume Ballet
699243f8ae core/state, light, trie: add UpdateContractCode to the Trie interface (#27476)
Verkle trees store the code inside the trie. This PR changes the interface to pass the code, as well as the dirty flag to tell the trie package if the code is dirty and needs to be updated. This is a no-op for the MPT and the odr trie.
2023-06-22 08:52:52 -04:00
Exca-DK
5520cd97a1 p2p/discover: swap verification order in discv4 ping handler (#27532)
In all other UDPv4 methods, the deadline is checked first. It seems weird to me that ping is an exception. Deadline comparison is also less resource intensive.

Co-authored-by: Exca-DK <Exca-DK@users.noreply.github.com>
2023-06-22 10:06:14 +02:00
James Prestwich
fd5d2ef0a6 internal/ethapi: quantity-encode storage keys in eth_getProof response (#27309)
This changes the eth_getProof method implementation to re-encode the requested
storage keys, canonicalizing them in the response. For backwards-compatibility reasons,
go-ethereum accepts non-canonical hex keys. Accepting them is fine, but we should
not mirror invalid inputs into the output.

Closes #27306

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-21 18:11:11 +02:00
Martin Holst Swende
713fc8bbe6 ethdb/pebble: fsync for batch writes (#27522)
This is likely the culprit behind several data corruption issues, e.g. where data has been
written to the freezer, but the deletion from pebble does not go through due to process
crash.
2023-06-21 18:08:12 +02:00
rjl493456442
6d2aeb43d5 cmd, core/state, eth, tests, trie: improve state reader (#27428)
The state availability is checked during the creation of a state reader.

-    In hash-based database, if the specified root node does not exist on disk disk, then
    the state reader won't be created and an error will be returned.

-    In path-based database, if the specified state layer is not available, then the
    state reader won't be created and an error will be returned.

This change also contains a stricter semantics regarding the `Commit` operation: once it has been performed, the trie is no longer usable, and certain operations will return an error.
2023-06-20 15:31:45 -04:00
jwasinger
8c288b528d internal/ethapi: use same state for each invocation within EstimateGas (#27505)
EstimateGas repeatedly executes a transaction, performing a binary search with multiple gas prices to determine proper pricing. Each call retrieves a new copy of the state (https://github.com/ethereum/go-ethereum/blob/master/internal/ethapi/api.go#L1017) . Because the pending/latest state can change during the execution of EstimateGas, this can potentially cause strange behavior (as noted here: https://github.com/ethereum/go-ethereum/pull/27502#issue-1761957009).

This PR modifies EstimateGas to retrieve the state once and use a copy of it for every call invocation it does.
2023-06-20 08:40:18 -04:00
Felix Lange
1affc1c08d core/txpool: remove use of errors.Join function (#27523)
his function was added in Go 1.20, but our compatibility target
is Go 1.19.
2023-06-20 13:51:59 +02:00
Dan Laine
154b016b6c core: use slices package for sorting (#27489)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-20 11:58:47 +02:00
Delweng
84b05d4f34 internal/build: ignore some files in FindMainPackages (#27521) 2023-06-20 10:42:13 +02:00
Dan Laine
b1ef0bfe03 eth: use slices package for sorting (#27490)
Also adds Hash.Less method for sorting purposes.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 23:38:57 +02:00
hero5512
9a167c45d1 core/txpool/legacypool: narrow down the scope of the variable (#27471)
Variables discarded, included can be defined closer to their usage.

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-06-19 23:30:39 +02:00
rjl493456442
ceca4578ca trie: remove parameter 'fromLevel' in Prove (#27512)
This removes the feature where top nodes of the proof can be elided.
It was intended to be used by the LES server, to save bandwidth 
when the client had already fetched parts of the state and only needed
some extra nodes to complete the proof. Alas, it never got implemented
in the client.
2023-06-19 16:28:40 +02:00
Marius van der Wijden
091c25d983 go.mod: update kzg libraries to use big-endian (#27510)
* go.mod: update kzg libraries to use big-endian

* go.sum: ran go mod tidy

* core/testdata/precompiles: fix blob verification test

* core/testdata/precompiles: fix blob verification test
2023-06-19 15:08:13 +03:00
Dan Laine
50ecb16de0 tests, trie: use slices package for sorting (#27496)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 11:41:31 +02:00
Dan Laine
87e510d963 internal/ethapi, les: use slices package for sorting (#27492)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 11:33:48 +02:00
Dan Laine
a848212709 consensus/clique: use slices package for sorting (#27488)
Also adds Address.Less for sorting use in other packages.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 09:04:16 +02:00
Dan Laine
4367ab499f metrics: use slices package for sorting (#27493)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 08:53:15 +02:00
Sanghee Choi
760fd0c79b consensus/clique: fix typo in comment (#27503) 2023-06-19 08:47:00 +02:00
John Chase
cd3b8c3d78 cmd/evm: fix typos in documentation (#27501) 2023-06-19 08:44:54 +02:00
Dan Laine
4544dc5f32 cmd/devp2p: use slices package for sorting (#27487) 2023-06-19 08:42:49 +02:00
Dan Laine
311b742c84 accounts/keystore: use slices package for sorting (#27485)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 08:34:47 +02:00
Koichi Shiraishi
f0b5af74a3 rpc: avoid use of cgo by hard-coding maxPathSize (#27447)
Package rpc uses cgo to find the maximum UNIX domain socket path 
length. If exceeded, a warning is printed. This is the only use of cgo in this
package. It seems excessive to depend on cgo just for this warning, so
we now hard-code the usual limit for Linux instead.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 08:06:58 +02:00
Martin Holst Swende
e4660a1181 core/txpool/legacypool: handle missing head in reset (#27479)
Fixes #27301, a crash that could occur during txpool reorg handling.
2023-06-19 07:58:04 +02:00
hero5512
a71b9b9ffa core/txpool/legacypool: remove redundant check for floatingRatio == 0 (#27477)
floatingRatio is a constant and always non-zero. So there is no need to
check for == 0.
2023-06-19 07:52:40 +02:00
John Chase
168d0cc3b3 internal/jsre/deps: fix typos in web3.js (#27500) 2023-06-19 07:50:56 +02:00
Dan Laine
5d75123cb7 ethdb/dbtest: use slices package for sorting (#27491) 2023-06-19 07:48:47 +02:00
Dan Laine
289c6c3b15 p2p: use slices package for sorting (#27494)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-19 07:48:12 +02:00
jin
46ec972c9c core/txpool/legacypool: reheap the tx list if london fork not enabled (#27481)
This change ensures Reheap will be called even before the London fork activates.
Since Reheap would otherwise only be called through `SetBaseFee` after London,
the list would just keep growing if the fork was not enabled or not reached yet.
2023-06-18 22:43:53 +02:00
Dan Laine
36ca59f1ec build: use slices package for sorting (#27486) 2023-06-18 15:09:00 +02:00
Péter Szilágyi
d40a255e97 all: move main transaction pool into a subpool (#27463)
* all: move main transaction pool into a subpool

* go.mod: remove superfluous updates

* core/txpool: review fixes, handle txs rejected by all subpools

* core/txpool: typos
2023-06-16 15:29:40 +03:00
John Chase
c375936e81 rlp: fix typos (#27484)
fix typos

Co-authored-by: john <yejiarui@123.com>
2023-06-16 15:21:43 +03:00
cui fliter
604da5c84b cmd/evm: fix typos in docs (#27478)
fix some typos

Signed-off-by: cui fliter <imcusg@gmail.com>
2023-06-15 08:55:00 -04:00
Martin Holst Swende
9cf9fae668 core/types: add support for BlobTxType receipts (#27470)
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-15 14:18:54 +02:00
aaronbuchwald
93ecd77d77 core: remove unnecessary log copy (#27475)
The logs in this function are pulled straight from disk in rawdb.ReadRawReceipts and 
also modified in receipts.DeriveFields, so removing the copy should be fine.
2023-06-15 13:52:06 +02:00
Sina Mahmoodi
7823ff6d06 eth/tracers: refactor exporting js buffer (#27472)
We had to do this workaround because it wasn't possible to export typed arrays from
JS to []byte. This was added in dop251/goja@2352993, so we can use the better way now.
2023-06-14 19:07:24 +02:00
Sanghee Choi
acc2a2ac61 node: remove unused error return from Attach (#27450)
node: Delete the unused error from return parameters of Node.Attach() func
2023-06-14 08:24:47 -04:00
zhiqiangxu
6f08c2f3f1 rpc: add method to test for subscription support (#25942)
This adds two ways to check for subscription support. First, one can now check
whether the transport method (HTTP/WS/etc.) is capable of subscriptions using
the new Client.SupportsSubscriptions method.

Second, the error returned by Subscribe can now reliably be tested using this
pattern:
    
    sub, err := client.Subscribe(...)
    if errors.Is(err, rpc.ErrNotificationsUnsupported) {
        // no subscription support
    }

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-14 14:04:41 +02:00
Freeman Jiang
8bbaf882a6 core/types: add "chainID" field to legacy tx JSON encoding (#27452)
Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com>
2023-06-13 14:46:45 +02:00
mmsqe
f3314bb6df rpc: add limit for batch request items and response size (#26681)
This PR adds server-side limits for JSON-RPC batch requests. Before this change, batches
were limited only by processing time. The server would pick calls from the batch and
answer them until the response timeout occurred, then stop processing the remaining batch
items.

Here, we are adding two additional limits which can be configured:

- the 'item limit': batches can have at most N items
- the 'response size limit': batches can contain at most X response bytes

These limits are optional in package rpc. In Geth, we set a default limit of 1000 items
and 25MB response size.

When a batch goes over the limit, an error response is returned to the client. However,
doing this correctly isn't always possible. In JSON-RPC, only method calls with a valid
`id` can be responded to. Since batches may also contain non-call messages or
notifications, the best effort thing we can do to report an error with the batch itself is
reporting the limit violation as an error for the first method call in the batch. If a batch is
too large, but contains only notifications and responses, the error will be reported with
a null `id`.

The RPC client was also changed so it can deal with errors resulting from too large
batches. An older client connected to the server code in this PR could get stuck
until the request timeout occurred when the batch is too large. **Upgrading to a version
of the RPC client containing this change is strongly recommended to avoid timeout issues.**

For some weird reason, when writing the original client implementation, @fjl worked off of
the assumption that responses could be distributed across batches arbitrarily. So for a
batch request containing requests `[A B C]`, the server could respond with `[A B C]` but
also with `[A B] [C]` or even `[A] [B] [C]` and it wouldn't make a difference to the
client.

So in the implementation of BatchCallContext, the client waited for all requests in the
batch individually. If the server didn't respond to some of the requests in the batch, the
client would eventually just time out (if a context was used).

With the addition of batch limits into the server, we anticipate that people will hit this
kind of error way more often. To handle this properly, the client now waits for a single
response batch and expects it to contain all responses to the requests.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-06-13 13:38:58 +02:00
hero5512
5ac4da3653 internal/ethapi: remove error return on RPCMarshalBlock (#27449)
rm error when marshal block to rpc type allen
2023-06-13 03:02:11 -04:00
jwasinger
174d267f48 miner: log number of withdrawals in block upon payload update (#27457) 2023-06-13 02:55:05 -04:00
Delweng
281e8cd5ab eth/filters: reuse handleLogs method for removed logs (#27438) 2023-06-08 11:40:22 +02:00
KAI
5c51ef8527 accounts/keystore: handle error for invalid key in DecryptKey (#27432)
Co-authored-by: KAI <kaili@coinsummer.io>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-06-07 15:10:42 +02:00
Stephen Guo
99eb0b52aa rlp: use identical receiver names for encBuffer methods (#27430) 2023-06-07 12:40:06 +02:00
Sina Mahmoodi
fbe432fa15 graphql: implement withdrawals (EIP-4895) (#27072)
implements withdrawals in graphql as per https://github.com/ethereum/execution-apis/pull/400
2023-06-06 12:33:25 -04:00
Delweng
0783cb7d91 eth,core: add api debug_getTrieFlushInterval (#27303)
* core,eth: add api debug_getTrieFlushInterval

Signed-off-by: jsvisa <delweng@gmail.com>

* eth/api_debug: comment of SetTrieFlushInterval

Signed-off-by: jsvisa <delweng@gmail.com>

* Apply suggestions from code review

---------

Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-06-06 08:41:44 -04:00
Péter Szilágyi
950d5643b1 core/txpool: make transaction validation reusable across packages (pools) (#27429)
* core/txpool: abstraction prep work for secondary pools (blob pool)

* core/txpool: leave subpool concepts to a followup pr

* les: fix tests using hard coded errors

* core/txpool: use bitmaps instead of maps for tx type filtering
2023-06-06 12:53:29 +03:00
Paul Lange
4cf708d30b les: remove unused var AdvertiseProtocolVersions (#27405) 2023-06-06 04:34:22 -04:00
Daniel Katzan
b8ee2877c5 core/txpool: fix minor flaw in isGapped check (#27404)
This fix a minor implementation issue with the newly introduced isGapped function and it is described in ticket: https://github.com/ethereum/go-ethereum/issues/27401
2023-06-06 04:29:41 -04:00
Martin Holst Swende
8eb0c2de76 cmd/evm: make evm blocktest output logs if so instructed (#27396)
* cmd/evm: make evm blocktest output logs if so instructed

* Apply suggestions from code review

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>

---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2023-06-06 04:27:40 -04:00
rjl493456442
0e5d2c7c53 core/state/snapshot, core/types, eth: move account definition to type (#27323)
* core/state/snapshot, core/types, eth: move account definition to type

* core, eth: revert snapshot Account API change
2023-06-06 11:17:39 +03:00
Marius van der Wijden
c537ace249 core: 4844 opcode and precompile (#27356)
* core: crypto: implement BLOBHASH and pointEval precompile

* core: crypto: fixed nitpicks, moved precompile return value

* core/vm: fix review comments
2023-06-05 16:43:25 +03:00
rjl493456442
380fb4e249 core/state: clear out cached state data when reset occurs (#27376)
* core/state: remove cached snap data if reset occurs

* core/state: address comment from peter

* core/state: skip revert in case data is nil
2023-06-05 16:25:57 +03:00
John Chase
78f7a6b7f2 graphql: simplify tx resolve (#27285) 2023-06-05 11:07:01 +02:00
Péter Szilágyi
a7b2106edf eth/downloader: drop beacon head updates if the syncer is restarting (#27397)
* eth/downloader: drop beacon head updates if the syncer is restarting

* eth/donwloader: v2 of the goroutine spike preventer
2023-06-05 09:59:38 +03:00
Péter Szilágyi
c7c84ca16c all: remove the Rinkeby testnet (#27406) 2023-06-02 14:03:21 +03:00
rjl493456442
15bd21f3c8 core/state: mark account as dirty when resetObject occurs (#27339)
This changes the journal logic to mark the state object dirty immediately when it
is reset. 

We're mostly adding this change to appease the fuzzer. Marking it dirty immediately
makes no difference in practice because accounts will always be modified by EVM
right after creation.
2023-06-01 11:09:32 +02:00
jin
2372fb2781 internal/web3ext: fix parameter count of miner_start (#27400) 2023-06-01 10:33:10 +02:00
Guillaume Ballet
45a3ab42aa core/state: move slot RLP encoding into the MPT implementation (#27000)
Continuing with a series of PRs to make the Trie interface more generic, this PR moves
the RLP encoding of storage slots inside the StateTrie and light.Trie implementations,
as other types of tries don't use RLP.
2023-06-01 10:29:41 +02:00
Felix Lange
ac86547b01 p2p/discover: add Table configuration and Nodes method (#27387)
* p2p/discover: remove ReadRandomNodes

Even though it's public, this method is not callable by code outside of
package p2p/discover because one can't get a valid instance of Table.

* p2p/discover: add Table.Nodes

* p2p/discover: make Table settings configurable

In unit tests and externally developed cmd/devp2p test runs, it can be
useful to tune the timer intervals used by Table.
2023-05-31 13:37:10 +02:00
Péter Szilágyi
008086f935 core, eth/downloader: validate blobtx.To at serialization time (#27393) 2023-05-31 13:08:15 +03:00
Péter Szilágyi
495692c9db core, eth/downloader, params: validate blob tx bodies (#27392) 2023-05-31 11:12:26 +03:00
Péter Szilágyi
1f9b69b36d consensus, core, eth/downloader, params: 4844 chain validation (#27382) 2023-05-31 10:21:13 +03:00
ucwong
cc2ab421e4 go.mod: golang.org/x upgrade (#27299)
go.mod:golang upgrade
2023-05-31 03:10:16 -04:00
rjl493456442
d4961881d7 miner: suspend miner if node is syncing (#27218)
Drop the notions of uncles, and disables activities while syncing

-  Disable activities (e.g. generate pending state) while node is syncing,
-  Disable empty block submission (but empty block is still kept for payload building),
-  Drop uncle notion since (ethash is already deprecated)
2023-05-31 03:09:49 -04:00
James Prestwich
61dcf76230 internal/ethapi: prevent unnecessary resource usage in eth_getProof implementation (#27310)
Deserialize hex keys early to shortcut on invalid input, and re-use the account storageTrie for each proof for each proof in the account, preventing repeated deep-copying of the trie.

Closes #27308

 --------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2023-05-31 02:52:27 -04:00
Seungbae Yu
8013a494fe event: move type fixation logic into Feed.init (#27249)
This is a minor optimization/refactoring of Feed.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-05-30 16:34:32 +02:00
ucwong
560dceb58e les, eth: fix typo in comment (#27369) 2023-05-30 14:55:03 +02:00
jwasinger
d789c68b66 eth: make debug_StorageRangeAt take a block hash or number (#27328)
eth: make StorageRangeAt take a block hash or number

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-05-30 08:16:28 -04:00
Guillaume Ballet
188817468e core/types: remove superfluous todo-comment (#27383) 2023-05-30 04:49:09 -04:00
Delweng
c57b3436f4 internal/ethapi: add more testcases for block/header rpc (#27325)
Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Sina Mahmoodi <1591639+s1na@users.noreply.github.com>
2023-05-29 08:52:08 -04:00
Delweng
13166210c8 eth: split api.go into namespace based files (#27263)
This change splits up the multiple API functions / namespaces currently defined in the eth package into different per-namespace files.
2023-05-29 05:09:34 -04:00
Delweng
1816cdc9fd internal/ethapi: don't return header size from rpc (#27347)
RPC methods `eth_getHeaderBy*` returned a size value which was meant for internal
processes. Please instead use `size` field returned by `eth_getBlockBy*` if you're interested
in the RLP encoded storage size of the block.

Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-25 15:19:58 +02:00
Delweng
db9a178ad2 eth/filters: retrieve logs in async (#27135)
This change implements async log retrievals via feeding logs in channels, instead of returning slices. This is a first step to implement #15063.  

---------

Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Sina Mahmoodi <1591639+s1na@users.noreply.github.com>
2023-05-25 08:40:28 -04:00
Delweng
9358b62fcb accounts: replace noarg fmt.Errorf with errors.New (#27331)
* accounts: replace noarg fmt.Errorf with errors.New

Signed-off-by: jsvisa <delweng@gmail.com>

* accounts: go autoimport

Signed-off-by: jsvisa <delweng@gmail.com>

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-25 08:25:58 -04:00
Delweng
6c732766c8 core,console: replace noarg fmt.Errorf with errors.New (#27332)
* core: replace noarg fmt.Errorf with errors.New

Signed-off-by: jsvisa <delweng@gmail.com>

* console: replace noarg fmt.Errorf with errors.New

Signed-off-by: jsvisa <delweng@gmail.com>

* core: go autoimport

Signed-off-by: jsvisa <delweng@gmail.com>

* core: dry

Signed-off-by: jsvisa <delweng@gmail.com>

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-25 08:24:09 -04:00
Martin Holst Swende
690249de7b params: begin v1.12.1 release cycle 2023-05-25 12:02:11 +02:00
Martin Holst Swende
e501b3b05d params: go-ethereum v1.12.0 stable 2023-05-25 12:01:00 +02:00
Martin Holst Swende
33fdd030b1 ethdb/pebble: fix NewBatchWithSize to set db (#27350) 2023-05-25 10:31:05 +03:00
Delweng
8a78a4f79f eth,consensus: replace noarg fmt.Errorf with errors.New (#27330)
* eth: replace noarg fmt.Errorf with errors.New

Signed-off-by: jsvisa <delweng@gmail.com>

* consensus: replace noarg fmt.Errorf with errors.New

Signed-off-by: jsvisa <delweng@gmail.com>

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-25 02:57:34 -04:00
Delweng
b21ba668e6 internal,tests: replace noarg fmt.Errorf with errors.New (#27335)
* internal: replace noarg fmt.Errorf with errors.New

Signed-off-by: jsvisa <delweng@gmail.com>

* tests: replace noarg fmt.Errorf with errors.New

Signed-off-by: jsvisa <delweng@gmail.com>

* tests: go autoimport

Signed-off-by: jsvisa <delweng@gmail.com>

* tests: go autoimport

Signed-off-by: jsvisa <delweng@gmail.com>

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-25 02:54:28 -04:00
Delweng
dd25a4f5ab les, signer, light: replace noarg fmt.Errorf with errors.New (#27336)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-25 02:51:13 -04:00
Delweng
21c87e0f1b crypto: replace noarg fmt.Errorf with errors.New (#27333)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-24 14:45:51 +02:00
Delweng
b0095eeb20 ethclient,event: replace noarg fmt.Errorf with errors.New (#27334)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-24 12:39:49 +02:00
Delweng
e9c3183c52 cmd: use errrors.New instead of empty fmt.Errorf (#27329)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-24 12:21:29 +02:00
Martin Holst Swende
9231770811 rpc: change BlockNumber constant values to match ethclient (#27219)
ethclient accepts certain negative block number values as specifiers for the "pending",
"safe" and "finalized" block. In case of "pending", the value accepted by ethclient (-1)
did not match rpc.PendingBlockNumber (-2).

This wasn't really a problem, but other values accepted by ethclient did match the
definitions in package rpc, and it's weird to have this one special case where they don't.

To fix it, we decided to change the values of the constants rather than changing ethclient.
The constant values are not otherwise significant. This is a breaking API change, but we
believe not a dangerous one.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-05-23 13:18:38 +02:00
Martin Holst Swende
1a18283e85 cmd/evm: make batched state-test execution possible (#27318)
implements the ability to run several state-tests in one instance. By not providing a statetest path to the `evm statetest` command, the path(s) will instead be read from `stdin`.
2023-05-23 06:23:17 -04:00
Park Changwan
bfded65ed8 core/state: do not ignore null addr while iterative dump (#27320)
fixes bug which caused the zero-address to be ignored during an iterative state-dump.

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-23 06:10:26 -04:00
minh-bq
a190da9d68 eth/tracers: fix flatCallTracer crasher (#27304)
FlatCallTracer had a crasher when it was passed `onlyTopCall: true` as config.
This PR ignores config fields inherited from the normal call tracer.
2023-05-23 11:02:50 +02:00
Chawin Aiemvaravutigul
5b792e0fdf accounts/abi: add ErrorById (#27277)
Adds `ErrorById` lookup
2023-05-22 12:45:55 -04:00
Sina Mahmoodi
b46d37ea52 graphql: upgrade UI to v2 (#27294)
Upgrades  graphiql to v2.4.4. The interface has become much nicer, and there are extra features like tabs, history, dark mode etc.

This change also now uses golang embed to bundle the resources.

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-22 08:15:05 -04:00
Delweng
6fe0252571 rpc, internal/cmdtest: increase timeout in tests (#27083)
This change gives the cmd-tests have a bit more time to finish before getting forcibly torn down.
2023-05-22 08:13:03 -04:00
Felix Lange
944e1a0f90 beacon/types: auto-generate SyncCommittee marshaling methods (#27296) 2023-05-19 17:05:50 +03:00
Shude Li
3223950a5d cmd/utils: do not check free disk space in dev mode (#27281) 2023-05-19 08:38:21 -04:00
Martin Holst Swende
99394adcb8 ethdb/pebble: prevent shutdown-panic (#27238)
One difference between pebble and leveldb is that the latter returns error when performing Get on a closed database, the former does a panic. This may be triggered during shutdown (see #27237)

This PR changes the pebble driver so we check that the db is not closed already, for several operations. It also adds tests to the db test-suite, so the previously implicit assumption of "not panic:ing at ops on closed database" is covered by tests.
2023-05-19 08:36:21 -04:00
Péter Szilágyi
85a4b82b33 all: tie timestamp based forks to the passage of London (#27279) 2023-05-19 11:27:19 +03:00
Shude Li
6a6318b1d2 go.mod: usegopkg.in/yaml.v3 instead of github.com/go-yaml/yaml (#27295) 2023-05-17 23:35:30 +02:00
Felföldi Zsolt
c08dc59aad beacon/types: add beacon chain data types (#27292)
* beacon/types: add beacon chain data types

* beacon/merkle: added comments

* go.mod: cleanups

---------

Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-05-17 17:39:33 +03:00
Felix Lange
41fafa47b6 go.mod: upgrade gencodec (#27288) 2023-05-17 15:03:38 +03:00
Stephen Guo
84c3799e21 rpc: more accurate checking of handler method signatures (#27287)
This changes the RPC server to ignore methods using *context.Context as parameter
and *error as return value type. Methods with such types would crash the server when
called.
2023-05-17 12:27:51 +02:00
Alex Mylonas
ae1d90e710 internal/ethapi: make NewAccount return EIP-55 format (#26973)
This change implements returning the address as EIP-55 encoded when creating a new account.
2023-05-17 04:29:56 -04:00
John Chase
2f2959d003 core/state/pruner: remove unused error-return (#27273) 2023-05-17 04:23:06 -04:00
Martin Holst Swende
eb83e7c540 core/state/snapshot: check difflayer staleness early (#27255)
This PR adds a staleness-check to AccountRLP, before checking the bloom-filter and potentially going directly into the disklayer.

---------

Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
2023-05-16 09:18:39 -04:00
Marius van der Wijden
d46f69dc7a tests/fuzzers/bn256: add PairingCheck fuzzer (#27252)
* tests/fuzzers/bn256: scale gnark result by constant

* tests/fuzzers/bn256: scale gnark result by constant
2023-05-16 07:27:54 -04:00
Delweng
6e3aa86a2b internal/ethapi: minor refactor in block serialization (#27268) 2023-05-16 10:40:47 +02:00
joohhnnn
c2148c644d core/asm: remove unused return value (#27272) 2023-05-16 10:14:04 +02:00
oseau
7369752999 rpc: websocket should respect the "HTTP_PROXY" by default (#27264)
rpc: the default dialer for websocket should respect the proxy environment variables like "HTTP_PROXY"
2023-05-15 08:48:06 +03:00
Justin Traglia
9ca84e6b0b crypto/kzg4844: upgrade c-kzg-4844 to v0.2.0 (#27257)
Upgrade c-kzg-4844 to v0.2.0
2023-05-12 20:16:14 +03:00
Péter Szilágyi
1982437259 core/types: un-ssz blob txs, add json marshalling and tweaks (#27256) 2023-05-12 20:14:29 +03:00
makcandrov
dffd804ca2 internal/ethapi: remove unused err-return (#27240) 2023-05-11 08:23:47 -04:00
zhiqiangxu
0b66d47449 internal/ethapi: make EstimateGas use latest block by default (#24363)
* EstimateGas should use LatestBlockNumber by default

* graphql: default to use latest for gas estimation

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-11 08:23:05 -04:00
Exca-DK
a340721aa9 metrics: use sync.map in registry (#27159) 2023-05-11 05:39:13 -04:00
rjl493456442
a14301823e all: new empty trie with types.EmptyRootHash instead of null (#27230) 2023-05-11 10:19:42 +03:00
Guillaume Ballet
7577b9c28f core/state: unexport NodeIterator (#27239) 2023-05-11 10:15:44 +03:00
ucwong
d17ec0ea66 ethdb/memorydb: init map with known size (#27241)
ethdb:init map with known size
2023-05-11 10:13:25 +03:00
Delweng
c8b0afb2c4 ethclient: acquire the rpc.Client (#27246)
Signed-off-by: jsvisa <delweng@gmail.com>
2023-05-11 10:09:16 +03:00
Péter Szilágyi
2169fa343a crypto/kzg4844: pull in the C and Go libs for KZG cryptography (#27155)
* cryto/kzg4844: pull in the C and Go libs for KZG cryptography

* go.mod: pull in the KZG libraries

* crypto/kzg4844: add basic becnhmarks for ballpark numbers

* cmd, crypto: integrate both CKZG and GoKZG all the time, add flag

* cmd/utils, crypto/kzg4844: run library init on startup

* crypto/kzg4844: make linter happy

* crypto/kzg4844: push missing file

* crypto/kzg4844: fully disable CKZG but leave in the sources

* build, crypto/kzg4844, internal: link CKZG by default and with portable mode

* crypto/kzg4844: drop verifying the trusted setup in gokzg

* internal/build: yolo until it works?

* cmd/utils: make flag description friendlier

Co-authored-by: Martin Holst Swende <martin@swende.se>

* crypto/ckzg: no need for double availability check

* build: tiny flag cleanup nitpick

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-10 14:54:14 +03:00
ucwong
ae7db289b8 p2p: initialize maps with known size (#27229) 2023-05-10 10:52:26 +02:00
Seungbae Yu
a742943c78 node: fix typos in comments (#27236) 2023-05-10 10:42:55 +02:00
ucwong
0fb1be0930 event: initialize maps with known size (#27233)
event: initialize maps with known size
2023-05-09 15:29:32 -04:00
Guillaume Ballet
c62da24dce cmd/utils: report the blocknumber when block import fails (#27213)
When block import fails, the error displays the number of the first block past the import batch, not the number of the failing block. This change fixes this problem by identifying which blocks fails and reporting its number.
2023-05-09 03:57:42 -04:00
ucwong
c798507642 miner: initialize maps with capacity (#27228)
* miner : initialize maps with known size

* miner:some reverts
2023-05-09 03:24:43 -04:00
rjl493456442
5021d36d35 all: port boring changes from pbss (#27176)
* all: port boring changes from pbss

* core, trie: address comments from martin

* trie: minor fixes

* core/rawdb: update comment

* core, eth, tests, trie: address comments

* tests, trie: add extra check when update trie database

* trie/triedb/hashdb: degrade the error to warning
2023-05-09 10:11:04 +03:00
ucwong
81d328a73e log: report error when ctx key is non-string (#27226)
* log/format.go : invalid string cast fix

* log: some polish

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-08 05:38:50 -04:00
joohhnnn
7ac08ba4e0 cmd/geth: rename variable 'extapi' (#27223)
rename parameter

In this case, the naming of "extapi" might create some confusion. Although it represents an External Signer Backend, its name could be mistaken for an API. In reality, it is a backend instance used for communicating with external signers. A better naming choice could be "extBackend" or "externalBackend" to more accurately describe that it is a backend instance rather than an API.
2023-05-08 10:01:14 +03:00
ucwong
cc8d40c65f core/state: initialize maps with known size (#27222)
* core/state : fix map size avoid resizing

* core/state : fixed size
2023-05-08 09:59:14 +03:00
sjlee1125
604e215d1b eth/tracers: add txHash field on txTraceResult (#27183)
This PR modifies the interface for the results of `debug_traceBlock` and `debug_traceCall` by adding the `txHash`, allowing users to identify which transaction's trace result corresponds to. 

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-05 08:59:13 -04:00
ucwong
ba09403113 core/txpool : fix map size avoid resizing (#27221) 2023-05-05 12:33:01 +03:00
rjl493456442
79a57d49cb eth/downloader: fix error aggregator (#27217) 2023-05-05 08:55:32 +03:00
s7v7nislands
ffda2c64c4 rpc: use atomic types (#27214)
rpc: use atomic type
2023-05-04 04:54:45 -04:00
Péter Szilágyi
dde2da0efb all: remove ethash pow, only retain shims needed for consensus and tests (#27178)
* all: remove ethash pow, only retain shims needed for consensus and tests

* all: thank you linter

* all: disallow launching Geth in legacy PoW mode

* cmd/env/internal/t8ntool: remove dangling ethash flag
2023-05-03 12:58:39 +03:00
Marius van der Wijden
ac3418def6 accounts/abi: resolve name conflict for methods starting with a number (#26999)
This adds logic to prepend 'M' or 'E' to Solidity identifiers when they would
otherwise violate Go identifier naming rules.

Closes #26972

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-05-02 14:27:37 +02:00
David Dzhalaev
29c33d9bab graphql, internal: fix typos in comments (#27184)
* ✏️ Fix typos

* ️ Revert changes

* Update internal/web3ext/web3ext.go

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-02 04:57:07 -04:00
Guillaume Ballet
7f6c045e0d core: remove unused ContractCode method from BlockChain (#27186) 2023-05-02 04:56:08 -04:00
Martin Holst Swende
7d1ebe51b7 p2p/discover: fix lint nit (#27206) 2023-05-02 04:36:11 -04:00
ucwong
a9d7cdaf6e core/types: go generate (#27196)
Fixes a discrepancy between source and generated files, which was introduced when ExcessDataGas was added in https://github.com/ethereum/go-ethereum/pull/27046.
2023-05-02 04:32:27 -04:00
Sina Mahmoodi
ae66009640 internal/ethapi: add block overrides to eth_call (#26414)
Adds an optional config parameter to eth_call which allows users to override block context fields (same functionality that was added to traceCall in #24871)

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-05-02 04:28:43 -04:00
chirag-bgh
52c246fac3 eth/gasprice: fix typo (#27202) 2023-05-02 04:24:35 -04:00
ucwong
a865e28f28 p2p/discover : typo (#27193) 2023-04-28 21:34:08 +03:00
ucwong
c387186f88 eth/ethconfig: go fmt (#27194) 2023-04-28 21:33:14 +03:00
Felix Lange
47cdea5ac5 p2p/discover: concurrent TALKREQ handling (#27112)
This changes TALKREQ message processing to run the handler on separate goroutine,
instead of running on the main discv5 dispatcher goroutine. It's better this way because
it allows the handler to perform blocking actions.

I'm also adding a new method TalkRequestToID here. The method allows implementing
a request flow where one node A sends TALKREQ to another node B, and node B later
sends a TALKREQ back. With TalkRequestToID, node B does not need the ENR of A to
send its request.
2023-04-28 11:03:43 +02:00
Delweng
8f373227ac cmd/geth: make account commands not require datadir lock (#27084)
Makes the `geth account ... ` commands usable even if a geth-process is already executing, since the account commands do not read the chaindata, it was not required for those to use the same locking mechanism. 

---
Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-04-27 06:57:29 -04:00
Péter Szilágyi
66c0c4e517 cmd, eth, les: replace Shanghai override flag with Cancun (#27171) 2023-04-26 18:17:37 +03:00
Stephen Guo
306d17749c light: use atomic type (#27169)
* light: use atomic type

* light: use a suitable name for the stopped switch in LightChain
2023-04-26 04:21:47 -04:00
Stephen Guo
25f9977f2d les: use atomic type (#27168) 2023-04-26 04:19:56 -04:00
Roberto Bayardo
f8aa623536 core/types: fix discrepancy in receipt.EffectiveGasPrice json encoding tags (#27114)
Regenerate receipt json code to remove omit empty. Previously, there was a discrepancy between the generated code and the source. 

---------

Co-authored-by: lightclient@protonmail.com <lightclient@protonmail.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-04-26 02:37:11 -04:00
rjl493456442
5d3f5805d5 trie: add node type common package (#27160)
* trie: add node type common package

In trie/types package, a few node wrappers are defined, which will be used
in both trie package, trie/snap package, etc. Therefore, a standalone common
package is created to put these stuffs.

* trie: rename trie/types to trie/trienode
2023-04-26 09:01:54 +03:00
Sina Mahmoodi
b1113aa07e eth: fix crash on querying finalized block (#27162)
eth: fix crash on querying nil finalized block
2023-04-25 09:15:43 -04:00
Sina Mahmoodi
2f98dd3838 graphql: encode Long values as hex (#26894)
This is a breaking GraphQL API change. All numeric values are now encoded as
hex strings. The motivation for this change is matching JSON-RPC outputs more
closely.

Numbers in query parameters are accepted as both decimal integers and hex strings.
2023-04-25 14:02:54 +02:00
Martin Holst Swende
9a12cc99de cmd/geth: remove DAO fork test (#27161)
* cmd/geth: fix test to not use explicit db

* cmd/geth: remove dao-test
2023-04-25 07:27:28 -04:00
Exca-DK
f8f95346f9 p2p/discover: add traffic metrics (#27008)
Co-authored-by: Exca-DK <dev@DESKTOP-RI45P4J.localdomain>
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
2023-04-25 12:12:34 +02:00
s7v7nislands
f541cad272 eth: use new atomic types (#27137) 2023-04-25 12:06:50 +02:00
rjl493456442
bbcb5ea37b core, trie: rework trie database (#26813)
* core, trie: rework trie database

* trie: fix comment
2023-04-24 10:38:52 +03:00
Péter Szilágyi
1e556d220c all: remove notion of trusted checkpoints in the post-merge world (#27147)
* all: remove notion of trusted checkpoints in the post-merge world

* light: remove unused function

* eth/ethconfig, les: remove unused config option

* les: make linter happy

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-04-24 09:37:10 +03:00
Péter Szilágyi
d3ece3a07c cmd/utils, node: switch to Pebble as the default db if none exists (#27136)
* cmd/utils, node: switch to Pebble as the default db if none exists

* node: fall back to LevelDB on platforms not supporting Pebble

* core/rawdb, node: default to Pebble at the node level

* cmd/geth: fix some tests explicitly using leveldb

* ethdb/pebble: allow double closes, makes tests simpler
2023-04-21 19:24:18 +03:00
Péter Szilágyi
bbc565ab05 core/types, params: add blob transaction type, RLP encoded for now (#27049)
* core/types, params: add blob transaction type, RLP encoded for now

* all: integrate Cancun (and timestamp based forks) into MakeSigner

* core/types: fix 2 back-and-forth type refactors

* core: fix review comment

* core/types: swap blob tx type id to 0x03
2023-04-21 12:52:02 +03:00
Martin Holst Swende
4ab4e4f3aa params: begin v1.11.7 release cycle 2023-04-20 20:16:04 +02:00
Martin Holst Swende
ea9e62ca3d params: go-ethereum v1.11.6 stable 2023-04-20 20:14:51 +02:00
rjl493456442
99f81d2724 all: refactor trie API (#26995)
In this PR, all TryXXX(e.g. TryGet) APIs of trie are renamed to XXX(e.g. Get) with an error returned.

The original XXX(e.g. Get) APIs are renamed to MustXXX(e.g. MustGet) and does not return any error -- they print a log output. A future PR will change the behaviour to panic on errorrs.
2023-04-20 06:57:24 -04:00
s7v7nislands
ae93e0b484 metrics: use atomic type (#27121) 2023-04-20 03:36:54 -04:00
Alex Beregszaszi
3f7afc3f57 core/vm: order opcodes properly (#27113) 2023-04-20 02:52:00 -04:00
Adrian Sutton
f2df2b1981 cmd/geth: rename --vmodule to --log.vmodule (#27071)
renames `--vmodule` to `--log.vmodule`, and prints a warning if the old form is used.
2023-04-19 07:18:02 -04:00
Martin Holst Swende
2b0a34bea6 cmd/devp2p: make crawler-route53-updater less verbose (#27116)
Follow-up to #26697, makes the crawler less verbose on route53-based scenarios.

It also changes the loglevel from debug to info on Updates, which are typically the root, and can be interesting to see.
2023-04-19 06:46:56 -04:00
s7v7nislands
3768b00747 consensus/ethash: use atomic type (#27068) 2023-04-18 14:54:06 +02:00
joohhnnn
b1972627d9 p2p: access embedded fields of Server directly (#27078) 2023-04-18 11:57:08 +02:00
Delweng
5e4d726e2a params: remove EIP150Hash from chainconfig (#27087)
The EIP150Hash was an idea where, after the fork, we hardcoded the forked hash as an extra defensive mechanism. It wasn't really used, since forks weren't contentious and for all the various testnets and private networks it's been a hassle to have around. 

This change removes that config field. 

---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-04-18 03:49:09 -04:00
Anusha
cb66eba85a core: fix comment to reflect function name (#27070) 2023-04-17 11:02:31 -04:00
Taeguk Kwon
bedf2856d1 signer/core: rename testdata files (#27063)
Sets a meaningful name on test-files
2023-04-17 10:36:47 -04:00
noel
8fe807c8f2 cmd/devp2p: fix erroneous log output in crawler (#27089)
cmd/devp2p: fix log of ignored recent nodes counter
2023-04-17 10:29:27 -04:00
Parithosh Jayanthi
5aa5295cf9 params: new sepolia bootnodes (#27099)
New sepolia bootnodes managed by EF devops
2023-04-17 04:15:25 -04:00
Péter Szilágyi
4a9fa31450 Merge pull request #27051 from sandakersmann/master
build: upgrade -dlgo version to Go 1.20.3
2023-04-08 17:13:55 +03:00
rjl493456442
b946b7a13b core, miner: drop transactions from the same sender when error occurs (#27038)
This PR unifies the error handling in miner. 

Whenever an error occur while applying a transaction, the transaction should be regarded as invalid and all following transactions from the same sender not executable because of the nonce restriction. The only exception is the `nonceTooLow` error which is handled separately.
2023-04-05 07:09:25 -04:00
Marius van der Wijden
230df98e4d core/txpool: disallow future churn by remote txs (#26907)
Prior to this change, it was possible that transactions are erroneously deemed as 'future' although they are in fact 'pending', causing them to be dropped due to 'future' not being allowed to replace 'pending'. 

This change fixes that, by doing a more in-depth inspection of the queue.
2023-04-05 04:59:32 -04:00
Marius Kjærstad
9d37102134 build: upgrade -dlgo version to Go 1.20.3 2023-04-04 22:24:30 +02:00
s7v7nislands
2adce0b066 eth/tracers: use atomic type (#27031)
Use the new atomic types in package eth/tracers

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-04-04 12:34:52 -04:00
Exca-DK
b4dcd1a391 metrics: make gauge_float64 and counter_float64 lock free (#27025)
Makes the float-gauges lock-free

name                      old time/op  new time/op  delta
CounterFloat64Parallel-8  1.45µs ±10%  0.85µs ± 6%  -41.65%  (p=0.008 n=5+5)

---------

Co-authored-by: Exca-DK <dev@DESKTOP-RI45P4J.localdomain>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-04-04 09:53:44 -04:00
Martin Holst Swende
ab1a404b01 all: remove debug-field from vm config (#27048)
This PR removes the Debug field from vmconfig, making it so that if a tracer is set, debug=true is implied.

---------

Co-authored-by: 0xTylerHolmes <tyler@ethereum.org>
Co-authored-by: Sina Mahmoodi <1591639+s1na@users.noreply.github.com>
2023-04-04 09:50:13 -04:00
Delweng
0b76eb3708 eth/tracers: report correct gasLimit in call tracers (#27029)
This includes a semantic change to the `callTracer` as well as `flatCallTracer`.
The value of field `gas` in the **first** call frame will change as follows:

- It previously contained gas available after initial deductions (i.e. tx costs)
- It will now contain the full tx gasLimit value

Signed-off-by: jsvisa <delweng@gmail.com>
2023-04-04 12:34:23 +02:00
Péter Szilágyi
d2cf49327f consensus/misc, params: add EIP-4844 blobfee conversions (#27041)
* consensus/misc, params: add EIP-4844 blobfee conversions

* consensus/misc: pull in fakeExponential test cases

* consensus/misc: reuse bigints

* consensus/misc: nit renames, additional larger testcase

---------

Co-authored-by: Roberto Bayardo <bayardo@alum.mit.edu>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-04-04 11:25:28 +03:00
Péter Szilágyi
91faf2c559 consensus, core/typer: add 4844 excessDataGas to header, tie it to Cancun (#27046) 2023-04-04 10:02:50 +03:00
joohhnnn
9b1a82c600 core/vm: clarify comment (#27045) 2023-04-04 02:59:40 -04:00
s7v7nislands
db18293c32 eth/downloader: use atomic types (#27030)
* eth/downloader: use atomic type

* Update eth/downloader/downloader_test.go

Co-authored-by: Martin Holst Swende <martin@swende.se>

* Update eth/downloader/downloader_test.go

Co-authored-by: Martin Holst Swende <martin@swende.se>

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-04-03 22:48:10 +03:00
Martin Holst Swende
beda6c41ad core/txpool: move some validation to outside of mutex (#27006)
Currently, most of transaction validation while holding the txpool mutex: one exception being an early-on signature check. 

This PR changes that, so that we do all non-stateful checks before we entering the mutex area. This means they can be performed in parallel, and to enable that, certain fields have been made atomic bools and uint64.
2023-04-03 07:16:57 -04:00
Martin Holst Swende
a25dd8064e test/fuzzers: fuzz rlp handling of big.Int and uint256.Int (#26917)
test/fuzzers: fuzz rlp handling of big.Lnt and uint256.Int
2023-04-03 05:42:34 -04:00
rjl493456442
94457cce07 cmd, miner, signer: avoid panic if keystore is not available (#27039)
* cmd, miner, singer: avoid panic if keystore is not available

* cmd/geth: print warning instead of panic
2023-04-03 05:08:06 -04:00
sudeep
7076ae00aa cmd/geth: enable log rotation (#26843)
This change enables log rotation, which can be activated using the flag --log.rotate. Additional parameters that can be given are: 

  - log.maxsize to set maximum size before files are rotated,
  - log.maxbackups to set how many files are retailed, 
  - log.maxage to configure max age of rotated files, 
  - log.compress whether to compress rotated files

The way to configure location of the logfile(s) is left unchanged, via the `log.logfile` parameter.  

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-04-03 05:05:36 -04:00
lightclient
2c5798464e common: delete MakeName (#27023)
common,p2p: remove unused function MakeName
2023-04-03 03:51:31 -04:00
ucwong
dc2f4b9304 go.mod : update snappy (#27027) 2023-04-03 03:35:13 -04:00
Guruprasad Kamath
bed07cd590 cmd/evm: use correct parent number for t8n base fee calculation (#27032)
Currently the t8n tool uses the same block number for the current block and its parent while calculating the base fee. This causes incorrect base fee calculation for the london fork block. This commit sets the parent block number to be one less than the current block number
2023-04-03 03:33:17 -04:00
aaronbuchwald
00a73fbcce accounts/abi/bind: handle UnpackLog with zero topics (#26920)
Adds error handling for the case that UnpackLog or UnpackLogIntoMap is called with a log that has zero topics.

---------

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-03-31 02:35:29 -04:00
s7v7nislands
b92d0ea3bb miner: use atomic type (#27013)
Use the new typed atomics in the miner package
2023-03-31 02:32:47 -04:00
openex
d0fbb10658 eth/catalyst: improve consensus heartbeat (#26896)
improve the heartbeat function that is no longer suitable in the current situation

Co-authored-by: “openex27” <“openexkevin@gmail.com”>
2023-03-30 15:09:35 -04:00
rjl493456442
9ce047452e common: fix json marshaller MixedcaseAddress (#26998)
Fix the json marshaller of MixedcaseAddress
2023-03-30 15:04:28 -04:00
s7v7nislands
50317bdace ethdb/pebble: use atomic type (#27014) 2023-03-30 15:02:14 -04:00
Adrian Sutton
2d1492821d cmd/geth: Add --log.format cli param (#27001)
Removes the new --log.logfmt directive and hides --log.json, replacing both with log.format=(json|logfmt|terminal). The hidden log.json option is still respected if log.format is not specified for backwards compatibility.

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-03-30 09:24:48 -04:00
Sina Mahmoodi
62fb7d3f85 graphql: revert storage access regression (#27007) 2023-03-30 06:57:49 -04:00
s7v7nislands
949cee2fe3 core: use atomic type (#27011) 2023-03-30 06:53:32 -04:00
Guillaume Ballet
a03490c6b2 remove @gballet as a GraphQL codeowner (#27012) 2023-03-30 04:58:23 -04:00
David Murdoch
7ca4f60a1a docs: update outdated DeriveSha docs comment (#26968) 2023-03-28 08:59:37 -04:00
Adrian Sutton
56c1f98f8a internal/debug: add log.logfmt flag to set logging to use logfmt (#26970) 2023-03-28 15:37:40 +03:00
jwasinger
fd94b4fcfa eth/tracers/native: prevent panic for LOG edge-cases (#26848)
This PR fixes OOM panic in the callTracer as well as panicing on
opcode validation errors (e.g. stack underflow) in callTracer and
prestateTracer.

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-03-28 11:46:53 +02:00
Sina Mahmoodi
a236e03d00 graphql: fix data races (#26965)
Fixes multiple data races caused by the fact that resolving fields are done concurrently by the graphql library. It also enforces caching at the stateobject level for account fields.
2023-03-28 03:08:10 -04:00
s7v7nislands
fb8a3aaf1e core/state: use atomic.Bool (#26992) 2023-03-28 03:06:50 -04:00
s7v7nislands
79532a25b1 core/bloombits: use atomic type (#26993) 2023-03-28 03:05:29 -04:00
s7v7nislands
881fed032c core/vm: use atomic.Bool (#26951)
Make use of new atomic types
---------

Co-authored-by: Felix Lange <fjl@twurst.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-03-27 09:40:20 -04:00
Delweng
117530b0e6 metrics/librato: ensure resp.body closed (#26969)
This change ensures that we call Close on a http response body, in various places in the source code (mostly tests)
2023-03-27 07:44:41 -04:00
Guillaume Ballet
41f89ca944 core/state, trie: remove Try prefix in Trie accessors (#26975)
This change renames StateTrie methods to remove the Try* prefix. 

We added the Trie methods with prefix 'Try' a long time ago, working
around the problem that most existing methods of Trie did not return the
database error. This weird naming convention has persisted until now.

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-03-27 10:48:46 +02:00
norwnd
df383addee ethclient: ensure returned subscription is nil on error (#26976) 2023-03-25 22:38:43 +01:00
ucwong
792d893ed0 rlp/rlpgen: print want/expect output string if mismatch (#26932)
Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2023-03-24 14:17:39 +01:00
Martin Holst Swende
0137bd69c5 go.mod: update golang.org/x/tools (#26960) 2023-03-24 12:39:20 +01:00
aaronbuchwald
b1acaf47aa eth/gasprice: change feehistory input type from int to uint64 (#26922)
Change input param type from int to uint64
2023-03-23 16:12:37 -04:00
Martin Holst Swende
f6c3a534a4 metrics/influxdb: use smaller dependency and reuse code between v1 and v2 reporters (#26963)
This change switches to use the smaller influxdata/influxdb1-client package instead of depending on the whole infuxdb package. The new smaller client is very similar to the influxdb-v2 client, which made it possible to refactor the two reporters to reuse code a lot more.
2023-03-23 15:12:32 -04:00
turboboost55
7dc100714d metrics: add cpu counters (#26796)
This PR adds counter metrics for the CPU system and the Geth process.
Currently the only metrics available for these items are gauges. Gauges are
fine when the consumer scrapes metrics data at the same interval as Geth
produces new values (every 3 seconds), but it is likely that most consumers
will not scrape that often. Intervals of 10, 15, or maybe even 30 seconds
are probably more common.

So the problem is, how does the consumer estimate what the CPU was doing in
between scrapes. With a counter, it's easy ... you just subtract two
successive values and divide by the time to get a nice, accurate average.
But with a gauge, you can't do that. A gauge reading is an instantaneous
picture of what was happening at that moment, but it gives you no idea
about what was going on between scrapes. Taking an average of values is
meaningless.
2023-03-23 14:13:50 +01:00
Guillaume Ballet
8990c92aea core/state: add account address to Trie slot accessors (#26934)
This changes the Trie interface to add the plain account address as a
parameter to all storage-related methods.

After the introduction of the TryAccount* functions, TryGet, TryUpdate and
TryDelete are now only meant to read an account's storage. In their current
form, they assume that an account storage is stored in a separate trie, and
that the hashing of the slot is independent of its account's address.

The proposed structure for a stateless storage breaks these two
assumptions: the hashing of a slot key requires the address and all slots
and accounts are stored in a single trie.

This PR therefore adds an address parameter to the interface. It is ignored
in the MPT version, so this change has no functional impact, however it
will reduce the diff size when merging verkle trees.
2023-03-23 11:52:22 +01:00
lightclient
37ecff0967 cmd/evm, tests: record preimages if dump is expected (#26955)
With #25287 we made it so that preimages were not recorded by default. This had the side effect that the evm command is no longer able to dump state since it does a preimage lookup to determine the address represented by a key.

This change enables the recording of preimages when the dump command is given.
2023-03-23 05:15:40 -04:00
Delweng
7f3fc15a8b core/rawdb: update freezertable read meter (#26946)
The meter for "for measuring the effective amount of data read" within the freezertable was never updated. This change remedies that. 
---------

Signed-off-by: jsvisa <delweng@gmail.com>
2023-03-23 03:34:40 -04:00
Marius van der Wijden
20f8eb756b eth/catalyst: fix races (#26950) 2023-03-22 13:36:26 -04:00
Martin Holst Swende
b3f43c89b3 core/vm: expose jumptable constructors (#26880)
When interacting with geth as a library to e.g. produce state tests, it is desirable to obtain the consensus-correct jumptable definition for a given fork. This changes adds accessors so the instructionset can be obtained and characteristics about opcodes can be inspected.
2023-03-21 07:14:47 -04:00
s7v7nislands
905a723fae core/rawdb: use atomic int added in go1.19 (#26935) 2023-03-21 07:10:23 -04:00
Péter Szilágyi
8a9a73c99b log: add special casing of uint256 into the logger (#26936) 2023-03-21 12:01:43 +02:00
Péter Szilágyi
2ed8013f08 build: allow building nightly archives via cron jobs (#26938) 2023-03-21 11:52:29 +02:00
Martin Holst Swende
7ecb578564 params: begin v1.11.6 release cycle 2023-03-21 09:04:26 +01:00
Martin Holst Swende
a38f410857 params: go-ethereum v1.11.5 stable 2023-03-21 09:03:04 +01:00
Marius van der Wijden
e6b6a8b738 core/txpool: allow future local transactions (#26930)
Local transactions should not be subject to the "future shouldn't churn pending txs" rule
2023-03-20 09:15:18 -04:00
Marius van der Wijden
5d23d21fff params: schedule shanghai fork on mainnet (#26908)
Schedules the shanghai hardfork on timestamp 1681338455 as discussed on ACDE 157: https://github.com/ethereum/execution-specs/pull/727
2023-03-20 07:38:34 -04:00
s7v7nislands
80ff0b4e6a core/txpool: use atomic int added in go1.19 (#26913)
Makes use of atomic.Uint64 instead of atomic by pointer
2023-03-20 04:12:24 -04:00
Marius van der Wijden
81b0aa0cc7 trie: reduce unit test time (#26918) 2023-03-20 04:09:35 -04:00
Darioush Jalali
ee8e83fa5f eth: fix output file permissions in admin_exportChain (#26912)
* api: Use 0700 file permissions for ExportChain

* change perm to 0644

* Update api.go

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-17 20:06:06 +02:00
Martin Holst Swende
58d0f6440b rlp: support for uint256 (#26898)
This adds built-in support in package rlp for encoding, decoding and generating code dealing with uint256.Int.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-17 06:51:55 -04:00
Darioush Jalali
b7bfbc1e64 trie, accounts/abi: add error-checks (#26914) 2023-03-17 06:19:51 -04:00
Darioush Jalali
f733657383 internal/ethapi: avoid int overflow in GetTransactionReceipt (#26911) 2023-03-16 23:53:39 +01:00
Marius van der Wijden
d8066dcde8 eth/catalyst: increase update consensus timeout (#26840)
Increases the time between consensus updates that we give the CL before we start warning the user.
2023-03-16 15:35:36 -04:00
rjl493456442
48d1bf0678 consensus: improve consensus engine definition (#26871)
Makes clear the distinction between Finalize and FinalizedAndAssemble:

- In Finalize function, a series of state operations are applied according to consensus rules. The statedb is mutated and the root hash can be checked and compared afterwards.

This function should be used in block processing(receive afrom network and apply it locally) but not block generation.

- In FinalizeAndAssemble function, after applying state mutations, the block is also to be assembled with the latest
  state root computed, updating the header. 

 This function should be used in block generation only.
2023-03-16 15:34:25 -04:00
rjl493456442
bba2a1bac5 core: show db error-info in case of mismatched hash root (#26870)
When a database failure occurs, bubble it up a into statedb, and report it in suitable places, such as during a 'bad block' report.
2023-03-16 03:12:34 -04:00
Felix Lange
f86913bc3e cmd/devp2p, cmd/geth: add version in --help output (#26895)
Not sure why this was removed, it's pretty useful to see the version
also in --help.
2023-03-15 14:34:36 +01:00
Jonathan Otto
6bc68f8d94 Increase websocket frame size (from erigon rpc client) (#26883)
This increases the maximum allowed message size to 32MB.

Originally submitted at https://github.com/ledgerwatch/erigon/pull/2739

example block failure: https://etherscan.io/tx/0x1317d973a55cedf9b0f2df6ea48e8077dd176f5444a3423368a46d6e4db89982#internal
2023-03-14 18:41:28 +01:00
Stephen Flynn
b5c9be3358 all: update links in documentation (#26882)
Co-authored-by: Stephen Flynn <stephen.flynn@gapac.com>
2023-03-14 10:23:49 -04:00
Martin Holst Swende
eca3d39c31 p2p/discover: pass invalid discv5 packets to Unhandled channel (#26699)
This makes it possible to run another protocol alongside discv5, by reading 
unhandled packets from the channel.
2023-03-14 12:40:40 +01:00
rjl493456442
c8a6b7100c core/state, trie: port changes from PBSS (#26763) 2023-03-14 04:50:53 -04:00
Felix Lange
94ff721911 .travis.yml: reenable PPA build on tag push (#26873) 2023-03-13 14:10:19 +01:00
lightclient
5f81db68c6 eth: return error if 'safe' or 'finalized' tag used pre-merge (#26862)
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-13 06:51:23 -04:00
ucwong
d1c5f918a3 core/txpool: use priceList.Put instead of heap.Push (#26863)
Minor refactor to use the 'intended' accessor
2023-03-13 04:45:25 -04:00
s7v7nislands
a20e38720c core: minor code refactor (#26852)
* core: refactor code

* core: drop it from this anonymous goroutine func
2023-03-13 04:02:50 -04:00
xiyang
ca61048178 code/vm: fix comment typo (#26865)
it should be constantinople rather than contantinople
2023-03-13 09:30:32 +02:00
Guruprasad Kamath
789de23d16 tests: define MuirGlacier fork (#26856)
add muir glacier to t8n
2023-03-10 15:47:05 -05:00
Felix Lange
4930614a09 params: begin v1.11.5 release cycle 2023-03-10 20:00:23 +01:00
Felix Lange
7e3b149be0 params: go-ethereum v1.11.4 stable 2023-03-10 19:53:52 +01:00
Marius van der Wijden
6cf2e921a7 core/txpool: implement additional DoS defenses (#26648)
This adds two new rules to the transaction pool:

- A future transaction can not evict a pending transaction.
- A transaction can not overspend available funds of a sender.

---

Co-authored-by: dwn1998 <42262393+dwn1998@users.noreply.github.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-03-10 18:30:26 +01:00
Felix Lange
564db9a95f core: add Timestamp method in BlockGen (#26844)
Since forks are now scheduled by block time, it can be necessary
to check the timestamp of a block while generating transactions.
2023-03-10 14:03:27 +01:00
panicalways
051493d9bf p2p: small comment typo (#26850)
Update server.go
2023-03-10 11:45:49 +02:00
Péter Szilágyi
df02799543 travis: only build PPAs nightly, not on every push, too heavy (#26846) 2023-03-09 16:44:54 +02:00
Roberto Bayardo
67ac5f0ae7 core, core/types: plain Message struct (#25977)
Here, the core.Message interface turns into a plain struct and
types.Message gets removed.

This is a breaking change to packages core and core/types. While we do
not promise API stability for package core, we do for core/types. An
exception can be made for types.Message, since it doesn't have any
purpose apart from invoking the state transition in package core.
types.Message was also marked deprecated by the same commit it
got added in, 4dca5d4db7 (November 2016).

The core.Message interface was added in December 2014, in commit
db494170dc, for the purpose of 'testing' state transitions. It's the
same change that made transaction struct fields private. Before that,
the state transition used *types.Transaction directly.

Over time, multiple implementations of the interface accrued across
different packages, since constructing a Message is required whenever
one wants to invoke the state transition. These implementations all
looked very similar, a struct with private fields exposing the fields
as accessor methods.

By changing Message into a struct with public fields we can remove all
these useless interface implementations. It will also hopefully
simplify future changes to the type with less updates to apply across
all of go-ethereum when a field is added to Message.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-09 14:19:12 +01:00
Martin Holst Swende
08f6a2a89d cmd/evm: update readmes for the tests (#26841) 2023-03-09 07:06:47 -05:00
Felix Lange
5395362e0f core/forkid: fix issue in validation test (#26544)
This changes the test to match the comment description. Using timestampedConfig in this test case is incorrect, the comment says 'local is at Gray Glacier' and isn't aware of more forks.
2023-03-09 06:37:44 -05:00
xiyang
1bf1168432 core/vm: fix typo in comment (#26838)
fixes eip 220 ->  2200
2023-03-09 04:39:17 -05:00
Martin Holst Swende
b80f05bde2 core/vm: use golang native big.Int (#26834)
reverts #26021, to use the upstream bigint instead.
2023-03-08 13:12:53 -05:00
Rafael Matias
e14043db71 params: remove EF azure bootnodes (#26828) 2023-03-08 11:13:56 +01:00
Daniel Fernandes
02796f6bee signer/core: accept all solidity primitive types for EIP-712 signing (#26770)
Accept all primitive types in Solidity for EIP-712 from intN, uintN, intN[], uintN[] for N as 0 to 256 in multiples of 8

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-03-08 02:48:53 -05:00
rjl493456442
f7661a662a core/rawdb: find smallest block stored in key-value store when chain gapped (#26719)
This change prints out more information about the problem, in the case where geth detects a gap between leveldb and ancients, so we can determine more exactly where the gap is (what the first missing is). Also prints out more metadata. 

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-03-08 02:39:13 -05:00
Felix Lange
bb4ac2d396 params: begin v1.11.4 release cycle 2023-03-07 18:18:59 +01:00
Felix Lange
5ed08c4735 params: go-ethereum v1.11.3 stable 2023-03-07 18:17:32 +01:00
Felix Lange
a54d91ac5a build: update to go 1.20.2 (#26824) 2023-03-07 18:16:21 +01:00
Marius van der Wijden
78429f7733 beacon/engine: don't omit empty withdrawals in ExecutionPayloadBodies (#26698)
This ensures the "withdrawals" field will always be present in responses
to getPayloadBodiesByRangeV1 and getPayloadBodiesByHashV1.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-07 16:30:04 +01:00
James Prestwich
1e3177de22 accounts/usbwallet: mitigate ledger app chunking issue (#26773)
This PR mitigates an issue with Ledger's on-device RLP deserialization, see
https://github.com/LedgerHQ/app-ethereum/issues/409

Ledger's RLP deserialization code does not validate the length of the RLP list received,
and it may prematurely enter the signing flow when a APDU chunk boundary falls immediately
before the EIP-155 chain_id when deserializing a transaction. Since the chain_id is
uninitialized, it is 0 during this signing flow. This may cause the user to accidentally
sign the transaction with chain_id = 0. That signature would be returned from the device 1
packet earlier than expected by the communication loop. The device blocks the
second-to-last packet waiting for the signer flow, and then errors on the successive
packet (which contains the chain_id, zeroed r, and zeroed s)

Since the signature's early arrival causes successive errors during the communication
process, geth does not parse the improper signature produced by the device, and therefore
no improperly-signed transaction can be created. User funds are not at risk.

We mitigate by selecting the highest chunk size that leaves at least 4 bytes in the
final chunk.
2023-03-07 15:20:04 +01:00
Sina Mahmoodi
41af42e97c eth/tracers/native: set created address to nil in case of failure (#26779)
Fixes #26073
2023-03-07 14:39:11 +01:00
Guruprasad Kamath
cb1f6bdbc8 cmd/evm: correct alloc for t8n testdata (#26822)
Fixes a minor error in the testdata
2023-03-07 05:32:52 -05:00
Adrian Sutton
39be753bf5 internal/ethapi: add tests for transaction types JSON marshal/unmarshal (#26667)
Checks that Transaction.MarshalJSON and newRPCTransaction JSON output can be parsed by Transaction.UnmarshalJSON

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-03-07 05:26:19 -05:00
rjl493456442
77e33e5a49 core, miner: revert block gas counter in case of invalid transaction (#26799)
This change fixes a flaw where, in certain scenarios, the block sealer did not accurately reset the remaining gas after failing to include an invalid transaction. Fixes #26791
2023-03-07 05:23:52 -05:00
Felix Lange
4688d3c8f4 ethclient: fix panic when requesting missing blocks (#26817)
This fixes a regression introduced by #26723.
Fixes #26816.
2023-03-07 05:21:23 -05:00
turboboost55
544e4a700b metrics: improve accuracy of CPU gauges (#26793)
This PR changes metrics collection to actually measure the time interval between collections, rather
than assume 3 seconds. I did some ad hoc profiling, and on slower hardware (eg, my Raspberry Pi 4)
I routinely saw intervals between 3.3 - 3.5 seconds, with some being as high as 4.5 seconds. This
will generally cause the CPU gauge readings to be too high, and in some cases can cause impossibly
large values for the CPU load metrics (eg. greater than 400 for a 4 core CPU).

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-07 00:29:48 +01:00
Marius van der Wijden
5bc2ef984f core, eth/catalyst: fix race conditions in tests (#26790)
Fixes a race in TestNewPayloadOnInvalidTerminalBlock where setting the TTD raced with
the miner. Solution: set the TTD on the blockchain config not the genesis config.

Also fixes a race in CopyHeader which resulted in race reports all over the place.
2023-03-06 23:32:27 +01:00
Felix Lange
87186148e0 core/types: add EffectiveGasPrice in Receipt (#26713)
This change adds a struct field EffectiveGasPrice in types.Receipt. The field is present
in RPC responses, but not in the Go struct, and thus can't easily be accessed via ethclient.

Co-authored-by: PulsarAI <dev@pulsar-systems.fi>
2023-03-06 17:19:41 +01:00
Péter Szilágyi
4c23fe97c5 eth: remove admin.peers[i].eth.head and difficulty (#26804) 2023-03-06 09:27:46 +02:00
Marius van der Wijden
d865a5d6ae core, params: schedule Shanghai on goerli (#26795)
* core: params: schedule Shanghai on goerli

* core/forkid: fix comment
2023-03-06 09:26:43 +02:00
Péter Szilágyi
27e59827d8 travi: remove strange leftover Go version 2023-03-03 12:26:04 +02:00
Péter Szilágyi
403cac71eb README, go.mod, event, internal/version: bump min Go to 1.19 (#26803) 2023-03-03 12:24:09 +02:00
Péter Szilágyi
010189538e core: fix a merge fault (#26802) 2023-03-03 12:11:39 +02:00
Péter Szilágyi
19f74fa3c0 core/rawdb, ethdb/pebble: disable pebble on openbsd (#26801) 2023-03-03 12:05:00 +02:00
Péter Szilágyi
cd31f2dee2 all: change chain head markers from block to header (#26777) 2023-03-02 08:29:15 +02:00
Peter (bitfly)
e1b98f49a5 ethclient: include withdrawals in ethclient block responses (#26778)
* include withdrawals in ethclient responses

* omit empty withdrawals array in json serialization
2023-02-28 15:40:24 +02:00
rjl493456442
2bb622ce40 ethdb/pebble: fix max memorytable size (#26776) 2023-02-28 15:34:12 +02:00
rjl493456442
98b0ea62b5 ethdb/pebble: fix range compaction (#26771)
* ethdb/pebble: fix range compaction

* ethdb/pebble: add comment
2023-02-28 15:32:51 +02:00
Dan Cline
2ea48f8a22 core: improve withdrawal index assignment in GenerateChain (#26756)
This fixes an issue where the withdrawal index was not calculated correctly
for multiple withdrawals in a single block.

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-02-28 11:46:32 +01:00
Chris Ziogas
2ad150d986 eth/tracers: add native flatCallTracer (aka parity style tracer) (#26377)
Adds support for a native call tracer with the Parity format, which outputs call frames
in a flat array. This tracer accepts the following options:

- `convertParityErrors: true` will convert error messages to match those of Parity
- `includePrecompiles: true` will report all calls to precompiles. The default
  matches Parity's behavior where CALL and STATICCALLs to precompiles are excluded

Incompatibilities with Parity include:

- Parity removes the result object in case of failure. This behavior is maintained
  with the exception of reverts. Revert output usually contains useful information,
  i.e. Solidity revert reason.
- The `gasUsed` field accounts for intrinsic gas (e.g. 21000 for simple transfers)
  and refunds unlike Parity
- Block rewards are not reported

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2023-02-28 13:54:37 +03:30
Martin Holst Swende
c155c8e179 cmd/devp2p: faster crawling + less verbose dns updates (#26697)
This improves the speed of DHT crawling by using concurrent requests.
It also removes logging of individual DNS updates.
2023-02-27 11:36:26 +01:00
Péter Szilágyi
ee530c0d5a Merge pull request #26721 from holiman/nocover
ci: disable coverage reporting in appveyor and travis
2023-02-23 13:24:31 +02:00
Péter Szilágyi
b3ae073488 eth: use the last announced finalized block as the sync ancient limit (#26685) 2023-02-23 13:22:41 +02:00
Martin Holst Swende
09a9ccdbce core/rawdb, node: use standalone flock dependency (#26633) 2023-02-23 09:11:50 +02:00
Nate Armstrong
a36c68f12c log: improve documentation (#26753)
Add usage examples
2023-02-22 07:39:41 -05:00
Péter Szilágyi
f6a7cc68d5 params: begin v.1.11.3 release cycle 2023-02-22 14:25:19 +02:00
Péter Szilágyi
73b01f40ce params: release Geth v1.11.2 2023-02-22 14:23:51 +02:00
Péter Szilágyi
f86f048646 common/math: allow HexOrDecimal to accept unquoted decimals too (#26758) 2023-02-22 13:55:09 +02:00
Yier
4034c675be eth/filters: fix a breaking change and return rpctransaction (#26757)
* eth/filters: fix a breaking change and return rpctransaction

* eth/filters: fix test cases

---------

Co-authored-by: Catror <me@catror.com>
2023-02-22 13:06:43 +02:00
rjl493456442
fe01a2f63b all: use unified emptyRootHash and emptyCodeHash (#26718)
The EmptyRootHash and EmptyCodeHash are defined everywhere in the codebase, this PR replaces all of them with unified one defined in core/types package, and also defines constants for TxRoot, WithdrawalsRoot and UncleRoot
2023-02-21 06:12:27 -05:00
Péter Szilágyi
2f20fd31ee core/rawdb: expose chain freezer constructor without internals (#26748) 2023-02-21 13:10:01 +02:00
Martin Holst Swende
6d2d126100 core: fix accessor mismatch for genesis state (#26747) 2023-02-21 12:18:33 +02:00
Péter Szilágyi
90d25514af core, eth: merge snap-sync chain download progress logs (#26676) 2023-02-21 12:17:34 +02:00
Sungwoo Kim
7d4db69607 cmd/geth: clarify dumpconfig options (#26729)
Clarifies the documentation around dumpconfi

Signed-off-by: Sungwoo Kim <git@sung-woo.kim>
2023-02-21 02:35:04 -05:00
rjl493456442
13ef21d467 Revert "core/trie: remove trie tracer (#26665)" (#26732)
This reverts commit 7c749c947a.
2023-02-20 09:54:52 -05:00
Péter Szilágyi
ba4267fcac build: enable Lunar Lobster PPA builds 2023-02-20 13:26:37 +02:00
Péter Szilágyi
41dee2623e build: fix Go 1.19.0 bootstrapper issues on 386 PPA 2023-02-20 12:36:46 +02:00
Péter Szilágyi
4519054816 build: fix (finaly?) the PPA env vars for Go bootstrapping 2023-02-20 11:31:19 +02:00
Péter Szilágyi
c02334be1e build: yet another weird PPA fix 2023-02-20 11:07:33 +02:00
Péter Szilágyi
165268430c internal/build: revert raising the chunk size for PPA 2023-02-20 10:43:55 +02:00
Péter Szilágyi
a43efceaf2 build: add some PPA debug logs, sigh 2023-02-20 10:31:35 +02:00
Péter Szilágyi
4ec4235fc4 build: fix gobootstrap path for the PPA 2023-02-20 10:09:00 +02:00
Péter Szilágyi
e1e2781105 build: fix setting env var, temp early exit 2023-02-20 09:57:37 +02:00
Péter Szilágyi
2166c86041 build: ship bootstrapper Go along with builder for PPA (#26731) 2023-02-20 08:53:15 +02:00
Felix Lange
1db978ca6b rpc: fix unmarshaling of null result in CallContext (#26723)
The change fixes unmarshaling of JSON null results into json.RawMessage.

---------

Co-authored-by: Jason Yuan <jason.yuan@curvegrid.com>
Co-authored-by: Jason Yuan <jason.yuan869@gmail.com>
2023-02-19 14:23:18 -05:00
Martin Holst Swende
7c749c947a core/trie: remove trie tracer (#26665)
This PR contains a small portion of the full pbss PR, namely

    Remove the tracer from trie (and comitter), and instead using an accessList.
    Related changes to the Nodeset.


---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2023-02-19 14:10:19 -05:00
Roman Krasiuk
15e5e6176b eth/catalyst: request too large error (#26722)
The method `GetPayloadBodiesByRangeV1` now returns "-38004: Too large request" error if the requested range is too large, according to spec

Co-authored-by: Martin Holst Swende <martin@swende.se>
2023-02-17 13:30:38 -05:00
Martin Holst Swende
a0d63bc69a ci: disable coverage reporting in appveyor and travis 2023-02-17 15:34:30 +01:00
Marius van der Wijden
6428663faf eth/catalyst: send INVALID instead of INVALID_BLOCK_HASH (#26696)
This change will break one hive test, but pass another and it will be the better way going forward
2023-02-17 05:25:09 -05:00
Martin Holst Swende
b40c10916c params: begin v1.11.2 release cycle 2023-02-16 20:53:16 +01:00
Martin Holst Swende
769610667d params: go-ethereum v1.11.1 stable 2023-02-16 20:51:51 +01:00
Martin Holst Swende
4d3525610e all: remove deprecated uses of math.rand (#26710)
This PR is a (superior) alternative to https://github.com/ethereum/go-ethereum/pull/26708, it handles deprecation, primarily two specific cases. 

`rand.Seed` is typically used in two ways
- `rand.Seed(time.Now().UnixNano())` -- we seed it, just to be sure to get some random, and not always get the same thing on every run. This is not needed, with global seeding, so those are just removed. 
- `rand.Seed(1)` this is typically done to ensure we have a stable test. If we rely on this, we need to fix up the tests to use a deterministic prng-source. A few occurrences like this has been replaced with a proper custom source. 

`rand.Read` has been replaced by `crypto/rand`.`Read` in this PR.
2023-02-16 14:36:58 -05:00
ucwong
e9d42499bb eth/downloader: fix typo (#26716) 2023-02-16 19:40:16 +02:00
Martin Holst Swende
13d7de77f4 eth/downloader: fix empty-body case in queue fetchresult (#26707) 2023-02-16 12:28:01 +02:00
Martin Holst Swende
645e3e86c4 core, eth/downloader: make body validation more strict (#26704) 2023-02-16 12:10:16 +02:00
rjl493456442
08bf8a60c3 core: check genesis state presence by disk read (#26703) 2023-02-16 12:09:41 +02:00
Péter Szilágyi
5ccc99b258 travis, build: update Go to 1.20.1 (#26653)
travis, build: update Go to 1.20
2023-02-16 09:00:45 +02:00
Martin Holst Swende
194b5c9152 params: begin v1.11.1 release cycle 2023-02-15 19:15:31 +01:00
1114 changed files with 62687 additions and 70583 deletions

2
.github/CODEOWNERS vendored
View File

@@ -10,7 +10,7 @@ core/ @karalabe @holiman @rjl493456442
eth/ @karalabe @holiman @rjl493456442
eth/catalyst/ @gballet
eth/tracers/ @s1na
graphql/ @gballet @s1na
graphql/ @s1na
les/ @zsfelfoldi @rjl493456442
light/ @zsfelfoldi @rjl493456442
node/ @fjl

View File

@@ -35,6 +35,6 @@ and help.
## Configuration, dependencies, and tests
Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/devguide)
Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/geth-developer/dev-guide)
for more details on configuring your environment, managing project dependencies
and testing procedures.

23
.github/workflows/go.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: i386 linux tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.21.4
- name: Run tests
run: go test ./...
env:
GOOS: linux
GOARCH: 386

3
.gitignore vendored
View File

@@ -47,3 +47,6 @@ profile.cov
/dashboard/assets/package-lock.json
**/yarn-error.log
logs/
tests/spec-tests/

View File

@@ -5,25 +5,10 @@ jobs:
allow_failures:
- stage: build
os: osx
go: 1.17.x
env:
- azure-osx
- azure-ios
- cocoapods-ios
include:
# This builder only tests code linters on latest version of Go
- stage: lint
os: linux
dist: bionic
go: 1.19.x
env:
- lint
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go lint
# These builders create the Docker sub-images for multi-arch push and each
# will attempt to push the multi-arch image if they are the last builder
- stage: build
@@ -31,7 +16,7 @@ jobs:
os: linux
arch: amd64
dist: bionic
go: 1.19.x
go: 1.21.x
env:
- docker
services:
@@ -48,7 +33,7 @@ jobs:
os: linux
arch: arm64
dist: bionic
go: 1.19.x
go: 1.21.x
env:
- docker
services:
@@ -60,40 +45,15 @@ jobs:
script:
- go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go
# This builder does the Ubuntu PPA upload
- stage: build
if: type = push
os: linux
dist: bionic
go: 1.19.x
env:
- ubuntu-ppa
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
addons:
apt:
packages:
- devscripts
- debhelper
- dput
- fakeroot
- python-bzrlib
- python-paramiko
script:
- echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts
- go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>"
# This builder does the Linux Azure uploads
- stage: build
if: type = push
os: linux
dist: bionic
sudo: required
go: 1.19.x
go: 1.21.x
env:
- azure-linux
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
addons:
@@ -120,46 +80,78 @@ jobs:
- go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# This builder does the OSX Azure uploads
- stage: build
if: type = push
os: osx
osx_image: xcode14.2
go: 1.21.x
env:
- azure-osx
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go install -dlgo
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go install -dlgo -arch arm64
- go run build/ci.go archive -arch arm64 -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# These builders run the tests
- stage: build
os: linux
arch: amd64
dist: bionic
go: 1.19.x
env:
- GO111MODULE=on
go: 1.21.x
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
- travis_wait 30 go run build/ci.go test $TEST_PACKAGES
- stage: build
if: type = pull_request
os: linux
arch: arm64
dist: bionic
go: 1.18.x
env:
- GO111MODULE=on
go: 1.20.x
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
- travis_wait 30 go run build/ci.go test $TEST_PACKAGES
- stage: build
os: linux
dist: bionic
go: 1.18.x
env:
- GO111MODULE=on
go: 1.20.x
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
- travis_wait 30 go run build/ci.go test $TEST_PACKAGES
# This builder does the Ubuntu PPA nightly uploads
- stage: build
if: type = cron || (type = push && tag ~= /^v[0-9]/)
os: linux
dist: bionic
go: 1.21.x
env:
- ubuntu-ppa
git:
submodules: false # avoid cloning ethereum/tests
addons:
apt:
packages:
- devscripts
- debhelper
- dput
- fakeroot
- python-bzrlib
- python-paramiko
script:
- echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts
- go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>"
# This builder does the Azure archive purges to avoid accumulating junk
- stage: build
if: type = cron
os: linux
dist: bionic
go: 1.19.x
go: 1.21.x
env:
- azure-purge
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
script:
@@ -170,9 +162,7 @@ jobs:
if: type = cron
os: linux
dist: bionic
go: 1.19.x
env:
- GO111MODULE=on
go: 1.21.x
script:
- go run build/ci.go test -race -coverage $TEST_PACKAGES
- travis_wait 30 go run build/ci.go test -race $TEST_PACKAGES

View File

@@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM golang:1.19-alpine as builder
FROM golang:1.21-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git

View File

@@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM golang:1.19-alpine as builder
FROM golang:1.21-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git

View File

@@ -6,7 +6,7 @@
GOBIN = ./build/bin
GO ?= latest
GORUN = env GO111MODULE=on go run
GORUN = go run
geth:
$(GORUN) build/ci.go install ./cmd/geth
@@ -23,7 +23,7 @@ lint: ## Run linters.
$(GORUN) build/ci.go lint
clean:
env GO111MODULE=on go clean -cache
go clean -cache
rm -fr build/_workspace/pkg/ $(GOBIN)/*
# The devtools target installs tools required for 'go generate'.

View File

@@ -16,7 +16,7 @@ archives are published at https://geth.ethereum.org/downloads/.
For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth).
Building `geth` requires both a Go (version 1.18 or later) and a C compiler. You can install
Building `geth` requires both a Go (version 1.19 or later) and a C compiler. You can install
them using your favourite package manager. Once the dependencies are installed, run
```shell
@@ -36,10 +36,10 @@ directory.
| Command | Description |
| :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/interface/command-line-options) for command line options. |
| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. |
| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. |
| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. |
| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/dapp/native-bindings) page for details. |
| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. |
| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. |
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). |
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
@@ -47,7 +47,7 @@ directory.
## Running `geth`
Going through all the possible command line flags is out of scope here (please consult our
[CLI Wiki page](https://geth.ethereum.org/docs/interface/command-line-options)),
[CLI Wiki page](https://geth.ethereum.org/docs/fundamentals/command-line-options)),
but we've enumerated a few common parameter combos to get you up to speed quickly
on how you can run your own `geth` instance.
@@ -82,10 +82,10 @@ This command will:
* Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag),
causing it to download more data in exchange for avoiding processing the entire history
of the Ethereum network, which is very CPU intensive.
* Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interface/javascript-console),
* Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interacting-with-geth/javascript-console),
(via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md)
(note: the `web3` version bundled within `geth` is very old, and not up to date with official docs),
as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/rpc/server).
as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc).
This tool is optional and if you leave it out you can always attach it to an already running
`geth` instance with `geth attach`.
@@ -123,15 +123,6 @@ use separate accounts for play and real money. Unless you manually move
accounts, `geth` will by default correctly separate the two networks and will not make any
accounts available between them.*
### Full node on the Rinkeby test network
Go Ethereum also supports connecting to the older proof-of-authority based test network
called [*Rinkeby*](https://www.rinkeby.io) which is operated by members of the community.
```shell
$ geth --rinkeby console
```
### Configuration
As an alternative to passing the numerous flags to the `geth` binary, you can also pass a
@@ -175,7 +166,7 @@ accessible from the outside.
As a developer, sooner rather than later you'll want to start interacting with `geth` and the
Ethereum network via your own programs and not manually through the console. To aid
this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/)
and [`geth` specific APIs](https://geth.ethereum.org/docs/rpc/server)).
and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)).
These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based
platforms, and named pipes on Windows).

View File

@@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"io"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
@@ -222,6 +223,17 @@ func (abi *ABI) EventByID(topic common.Hash) (*Event, error) {
return nil, fmt.Errorf("no event with id: %#x", topic.Hex())
}
// ErrorByID looks up an error by the 4-byte id,
// returns nil if none found.
func (abi *ABI) ErrorByID(sigdata [4]byte) (*Error, error) {
for _, errABI := range abi.Errors {
if bytes.Equal(errABI.ID[:4], sigdata[:]) {
return &errABI, nil
}
}
return nil, fmt.Errorf("no error with id: %#x", sigdata[:])
}
// HasFallback returns an indicator whether a fallback function is included.
func (abi *ABI) HasFallback() bool {
return abi.Fallback.Type == Fallback
@@ -235,21 +247,65 @@ func (abi *ABI) HasReceive() bool {
// revertSelector is a special function selector for revert reason unpacking.
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
// panicSelector is a special function selector for panic reason unpacking.
var panicSelector = crypto.Keccak256([]byte("Panic(uint256)"))[:4]
// panicReasons map is for readable panic codes
// see this linkage for the details
// https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require
// the reason string list is copied from ether.js
// https://github.com/ethers-io/ethers.js/blob/fa3a883ff7c88611ce766f58bdd4b8ac90814470/src.ts/abi/interface.ts#L207-L218
var panicReasons = map[uint64]string{
0x00: "generic panic",
0x01: "assert(false)",
0x11: "arithmetic underflow or overflow",
0x12: "division or modulo by zero",
0x21: "enum overflow",
0x22: "invalid encoded storage byte array accessed",
0x31: "out-of-bounds array access; popping on an empty array",
0x32: "out-of-bounds access of an array or bytesN",
0x41: "out of memory",
0x51: "uninitialized function",
}
// UnpackRevert resolves the abi-encoded revert reason. According to the solidity
// spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert,
// the provided revert reason is abi-encoded as if it were a call to a function
// `Error(string)`. So it's a special tool for it.
// the provided revert reason is abi-encoded as if it were a call to function
// `Error(string)` or `Panic(uint256)`. So it's a special tool for it.
func UnpackRevert(data []byte) (string, error) {
if len(data) < 4 {
return "", errors.New("invalid data for unpacking")
}
if !bytes.Equal(data[:4], revertSelector) {
switch {
case bytes.Equal(data[:4], revertSelector):
typ, err := NewType("string", "", nil)
if err != nil {
return "", err
}
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
if err != nil {
return "", err
}
return unpacked[0].(string), nil
case bytes.Equal(data[:4], panicSelector):
typ, err := NewType("uint256", "", nil)
if err != nil {
return "", err
}
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
if err != nil {
return "", err
}
pCode := unpacked[0].(*big.Int)
// uint64 safety check for future
// but the code is not bigger than MAX(uint64) now
if pCode.IsUint64() {
if reason, ok := panicReasons[pCode.Uint64()]; ok {
return reason, nil
}
}
return fmt.Sprintf("unknown panic code: %#x", pCode), nil
default:
return "", errors.New("invalid data for unpacking")
}
typ, _ := NewType("string", "", nil)
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
if err != nil {
return "", err
}
return unpacked[0].(string), nil
}

View File

@@ -120,6 +120,7 @@ var methods = map[string]Method{
}
func TestReader(t *testing.T) {
t.Parallel()
abi := ABI{
Methods: methods,
}
@@ -151,6 +152,7 @@ func TestReader(t *testing.T) {
}
func TestInvalidABI(t *testing.T) {
t.Parallel()
json := `[{ "type" : "function", "name" : "", "constant" : fals }]`
_, err := JSON(strings.NewReader(json))
if err == nil {
@@ -170,6 +172,7 @@ func TestInvalidABI(t *testing.T) {
// constructor(uint256 a, uint256 b) public{}
// }
func TestConstructor(t *testing.T) {
t.Parallel()
json := `[{ "inputs": [{"internalType": "uint256","name": "a","type": "uint256" },{ "internalType": "uint256","name": "b","type": "uint256"}],"stateMutability": "nonpayable","type": "constructor"}]`
method := NewMethod("", "", Constructor, "nonpayable", false, false, []Argument{{"a", Uint256, false}, {"b", Uint256, false}}, nil)
// Test from JSON
@@ -199,6 +202,7 @@ func TestConstructor(t *testing.T) {
}
func TestTestNumbers(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -236,6 +240,7 @@ func TestTestNumbers(t *testing.T) {
}
func TestMethodSignature(t *testing.T) {
t.Parallel()
m := NewMethod("foo", "foo", Function, "", false, false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil)
exp := "foo(string,string)"
if m.Sig != exp {
@@ -274,6 +279,7 @@ func TestMethodSignature(t *testing.T) {
}
func TestOverloadedMethodSignature(t *testing.T) {
t.Parallel()
json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
@@ -297,6 +303,7 @@ func TestOverloadedMethodSignature(t *testing.T) {
}
func TestCustomErrors(t *testing.T) {
t.Parallel()
json := `[{ "inputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ],"name": "MyError", "type": "error"} ]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
@@ -311,6 +318,7 @@ func TestCustomErrors(t *testing.T) {
}
func TestMultiPack(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -348,6 +356,7 @@ func ExampleJSON() {
}
func TestInputVariableInputLength(t *testing.T) {
t.Parallel()
const definition = `[
{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
@@ -476,6 +485,7 @@ func TestInputVariableInputLength(t *testing.T) {
}
func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Error(err)
@@ -650,6 +660,7 @@ func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
}
func TestDefaultFunctionParsing(t *testing.T) {
t.Parallel()
const definition = `[{ "name" : "balance", "type" : "function" }]`
abi, err := JSON(strings.NewReader(definition))
@@ -663,6 +674,7 @@ func TestDefaultFunctionParsing(t *testing.T) {
}
func TestBareEvents(t *testing.T) {
t.Parallel()
const definition = `[
{ "type" : "event", "name" : "balance" },
{ "type" : "event", "name" : "anon", "anonymous" : true},
@@ -739,6 +751,7 @@ func TestBareEvents(t *testing.T) {
//
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
func TestUnpackEvent(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -777,6 +790,7 @@ func TestUnpackEvent(t *testing.T) {
}
func TestUnpackEventIntoMap(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -827,6 +841,7 @@ func TestUnpackEventIntoMap(t *testing.T) {
}
func TestUnpackMethodIntoMap(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -877,6 +892,7 @@ func TestUnpackMethodIntoMap(t *testing.T) {
}
func TestUnpackIntoMapNamingConflict(t *testing.T) {
t.Parallel()
// Two methods have the same name
var abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"get","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
@@ -960,6 +976,7 @@ func TestUnpackIntoMapNamingConflict(t *testing.T) {
}
func TestABI_MethodById(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -992,6 +1009,7 @@ func TestABI_MethodById(t *testing.T) {
}
func TestABI_EventById(t *testing.T) {
t.Parallel()
tests := []struct {
name string
json string
@@ -1057,9 +1075,39 @@ func TestABI_EventById(t *testing.T) {
}
}
func TestABI_ErrorByID(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(`[
{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"MyError1","type":"error"},
{"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"x","type":"tuple"},{"internalType":"address","name":"y","type":"address"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"z","type":"tuple"}],"name":"MyError2","type":"error"},
{"inputs":[{"internalType":"uint256[]","name":"x","type":"uint256[]"}],"name":"MyError3","type":"error"}
]`))
if err != nil {
t.Fatal(err)
}
for name, m := range abi.Errors {
a := fmt.Sprintf("%v", &m)
var id [4]byte
copy(id[:], m.ID[:4])
m2, err := abi.ErrorByID(id)
if err != nil {
t.Fatalf("Failed to look up ABI error: %v", err)
}
b := fmt.Sprintf("%v", m2)
if a != b {
t.Errorf("Error %v (id %x) not 'findable' by id in ABI", name, id)
}
}
// test unsuccessful lookups
if _, err = abi.ErrorByID([4]byte{}); err == nil {
t.Error("Expected error: no error with this id")
}
}
// TestDoubleDuplicateMethodNames checks that if transfer0 already exists, there won't be a name
// conflict and that the second transfer method will be renamed transfer1.
func TestDoubleDuplicateMethodNames(t *testing.T) {
t.Parallel()
abiJSON := `[{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer0","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"},{"name":"customFallback","type":"string"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -1089,6 +1137,7 @@ func TestDoubleDuplicateMethodNames(t *testing.T) {
// event send();
// }
func TestDoubleDuplicateEventNames(t *testing.T) {
t.Parallel()
abiJSON := `[{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "a","type": "uint256"}],"name": "send","type": "event"},{"anonymous": false,"inputs": [],"name": "send0","type": "event"},{ "anonymous": false, "inputs": [],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -1116,6 +1165,7 @@ func TestDoubleDuplicateEventNames(t *testing.T) {
// event send(uint256, uint256);
// }
func TestUnnamedEventParam(t *testing.T) {
t.Parallel()
abiJSON := `[{ "anonymous": false, "inputs": [{ "indexed": false,"internalType": "uint256", "name": "","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "","type": "uint256"}],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -1145,9 +1195,13 @@ func TestUnpackRevert(t *testing.T) {
{"", "", errors.New("invalid data for unpacking")},
{"08c379a1", "", errors.New("invalid data for unpacking")},
{"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil},
{"4e487b710000000000000000000000000000000000000000000000000000000000000000", "generic panic", nil},
{"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil},
}
for index, c := range cases {
index, c := index, c
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
t.Parallel()
got, err := UnpackRevert(common.Hex2Bytes(c.input))
if c.expectErr != nil {
if err == nil {

View File

@@ -20,20 +20,34 @@ import (
"fmt"
"reflect"
"strings"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi"
fuzz "github.com/google/gofuzz"
)
// TestReplicate can be used to replicate crashers from the fuzzing tests.
// Just replace testString with the data in .quoted
func TestReplicate(t *testing.T) {
t.Parallel()
//t.Skip("Test only useful for reproducing issues")
fuzzAbi([]byte("\x20\x20\x20\x20\x20\x20\x20\x20\x80\x00\x00\x00\x20\x20\x20\x20\x00"))
//fuzzAbi([]byte("asdfasdfkadsf;lasdf;lasd;lfk"))
}
// FuzzABI is the main entrypoint for fuzzing
func FuzzABI(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzAbi(data)
})
}
var (
names = []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
stateMut = []string{"", "pure", "view", "payable"}
stateMutabilites = []*string{&stateMut[0], &stateMut[1], &stateMut[2], &stateMut[3]}
pays = []string{"", "true", "false"}
payables = []*string{&pays[0], &pays[1]}
vNames = []string{"a", "b", "c", "d", "e", "f", "g"}
varNames = append(vNames, names...)
varTypes = []string{"bool", "address", "bytes", "string",
names = []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
stateMut = []string{"pure", "view", "payable"}
pays = []string{"true", "false"}
vNames = []string{"a", "b", "c", "d", "e", "f", "g"}
varNames = append(vNames, names...)
varTypes = []string{"bool", "address", "bytes", "string",
"uint8", "int8", "uint8", "int8", "uint16", "int16",
"uint24", "int24", "uint32", "int32", "uint40", "int40", "uint48", "int48", "uint56", "int56",
"uint64", "int64", "uint72", "int72", "uint80", "int80", "uint88", "int88", "uint96", "int96",
@@ -47,7 +61,7 @@ var (
"bytes32", "bytes"}
)
func unpackPack(abi abi.ABI, method string, input []byte) ([]interface{}, bool) {
func unpackPack(abi ABI, method string, input []byte) ([]interface{}, bool) {
if out, err := abi.Unpack(method, input); err == nil {
_, err := abi.Pack(method, out...)
if err != nil {
@@ -63,7 +77,7 @@ func unpackPack(abi abi.ABI, method string, input []byte) ([]interface{}, bool)
return nil, false
}
func packUnpack(abi abi.ABI, method string, input *[]interface{}) bool {
func packUnpack(abi ABI, method string, input *[]interface{}) bool {
if packed, err := abi.Pack(method, input); err == nil {
outptr := reflect.New(reflect.TypeOf(input))
err := abi.UnpackIntoInterface(outptr.Interface(), method, packed)
@@ -79,12 +93,12 @@ func packUnpack(abi abi.ABI, method string, input *[]interface{}) bool {
return false
}
type args struct {
type arg struct {
name string
typ string
}
func createABI(name string, stateMutability, payable *string, inputs []args) (abi.ABI, error) {
func createABI(name string, stateMutability, payable *string, inputs []arg) (ABI, error) {
sig := fmt.Sprintf(`[{ "type" : "function", "name" : "%v" `, name)
if stateMutability != nil {
sig += fmt.Sprintf(`, "stateMutability": "%v" `, *stateMutability)
@@ -111,60 +125,55 @@ func createABI(name string, stateMutability, payable *string, inputs []args) (ab
sig += "} ]"
}
sig += `}]`
return abi.JSON(strings.NewReader(sig))
//fmt.Printf("sig: %s\n", sig)
return JSON(strings.NewReader(sig))
}
func runFuzzer(input []byte) int {
good := false
fuzzer := fuzz.NewFromGoFuzz(input)
name := names[getUInt(fuzzer)%len(names)]
stateM := stateMutabilites[getUInt(fuzzer)%len(stateMutabilites)]
payable := payables[getUInt(fuzzer)%len(payables)]
maxLen := 5
for k := 1; k < maxLen; k++ {
var arg []args
for i := k; i > 0; i-- {
argName := varNames[i]
argTyp := varTypes[getUInt(fuzzer)%len(varTypes)]
if getUInt(fuzzer)%10 == 0 {
argTyp += "[]"
} else if getUInt(fuzzer)%10 == 0 {
arrayArgs := getUInt(fuzzer)%30 + 1
argTyp += fmt.Sprintf("[%d]", arrayArgs)
}
arg = append(arg, args{
name: argName,
typ: argTyp,
})
func fuzzAbi(input []byte) {
var (
fuzzer = fuzz.NewFromGoFuzz(input)
name = oneOf(fuzzer, names)
stateM = oneOfOrNil(fuzzer, stateMut)
payable = oneOfOrNil(fuzzer, pays)
arguments []arg
)
for i := 0; i < upTo(fuzzer, 10); i++ {
argName := oneOf(fuzzer, varNames)
argTyp := oneOf(fuzzer, varTypes)
switch upTo(fuzzer, 10) {
case 0: // 10% chance to make it a slice
argTyp += "[]"
case 1: // 10% chance to make it an array
argTyp += fmt.Sprintf("[%d]", 1+upTo(fuzzer, 30))
default:
}
abi, err := createABI(name, stateM, payable, arg)
if err != nil {
continue
}
structs, b := unpackPack(abi, name, input)
c := packUnpack(abi, name, &structs)
good = good || b || c
arguments = append(arguments, arg{name: argName, typ: argTyp})
}
if good {
return 1
abi, err := createABI(name, stateM, payable, arguments)
if err != nil {
//fmt.Printf("err: %v\n", err)
panic(err)
}
return 0
structs, _ := unpackPack(abi, name, input)
_ = packUnpack(abi, name, &structs)
}
func Fuzz(input []byte) int {
return runFuzzer(input)
}
func getUInt(fuzzer *fuzz.Fuzzer) int {
func upTo(fuzzer *fuzz.Fuzzer, max int) int {
var i int
fuzzer.Fuzz(&i)
if i < 0 {
i = -i
if i < 0 {
return 0
}
return (-1 - i) % max
}
return i
return i % max
}
func oneOf(fuzzer *fuzz.Fuzzer, options []string) string {
return options[upTo(fuzzer, len(options))]
}
func oneOfOrNil(fuzzer *fuzz.Fuzzer, options []string) *string {
if i := upTo(fuzzer, len(options)+1); i < len(options) {
return &options[i]
}
return nil
}

View File

@@ -80,7 +80,7 @@ func (arguments Arguments) isTuple() bool {
func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) {
if len(data) == 0 {
if len(arguments.NonIndexed()) != 0 {
return nil, errors.New("abi: attempting to unmarshall an empty string while arguments are expected")
return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
return make([]interface{}, 0), nil
}
@@ -95,7 +95,7 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
}
if len(data) == 0 {
if len(arguments.NonIndexed()) != 0 {
return errors.New("abi: attempting to unmarshall an empty string while arguments are expected")
return errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
return nil // Nothing to unmarshal, return
}

View File

@@ -56,7 +56,7 @@ func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
}
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
// an decrypted key from a keystore.
// a decrypted key from a keystore.
//
// Deprecated: Use NewKeyStoreTransactorWithChainID instead.
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
@@ -117,7 +117,7 @@ func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.I
}
// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from
// an decrypted key from a keystore.
// a decrypted key from a keystore.
func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) {
if chainID == nil {
return nil, ErrNoChainID

View File

@@ -29,13 +29,17 @@ import (
var (
// ErrNoCode is returned by call and transact operations for which the requested
// recipient contract to operate on does not exist in the state db or does not
// have any code associated with it (i.e. suicided).
// have any code associated with it (i.e. self-destructed).
ErrNoCode = errors.New("no contract code at given address")
// ErrNoPendingState is raised when attempting to perform a pending state action
// on a backend that doesn't implement PendingContractCaller.
ErrNoPendingState = errors.New("backend does not support pending state")
// ErrNoBlockHashState is raised when attempting to perform a block hash action
// on a backend that doesn't implement BlockHashContractCaller.
ErrNoBlockHashState = errors.New("backend does not support block hash state")
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
// an empty contract behind.
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
@@ -64,6 +68,17 @@ type PendingContractCaller interface {
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
}
// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
// Call will try to discover this interface when access to a block by hash is requested.
// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
type BlockHashContractCaller interface {
// CodeAtHash returns the code of the given account in the state at the specified block hash.
CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error)
// CallContractAtHash executes an Ethereum contract call against the state at the specified block hash.
CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error)
}
// ContractTransactor defines the methods needed to allow operating with a contract
// on a write only basis. Besides the transacting method, the remainder are helpers
// used when the user does not provide some needed values, but rather leaves it up

View File

@@ -50,6 +50,7 @@ var _ bind.ContractBackend = (*SimulatedBackend)(nil)
var (
errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
errBlockHashUnsupported = errors.New("simulatedBackend cannot access blocks by hash other than the latest block")
errBlockDoesNotExist = errors.New("block does not exist in blockchain")
errTransactionDoesNotExist = errors.New("transaction does not exist")
)
@@ -95,7 +96,10 @@ func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.Genesis
backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
backend.events = filters.NewEventSystem(backend.filterSystem, false)
backend.rollback(blockchain.CurrentBlock())
header := backend.blockchain.CurrentBlock()
block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
backend.rollback(block)
return backend
}
@@ -135,7 +139,10 @@ func (b *SimulatedBackend) Rollback() {
b.mu.Lock()
defer b.mu.Unlock()
b.rollback(b.blockchain.CurrentBlock())
header := b.blockchain.CurrentBlock()
block := b.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
b.rollback(block)
}
func (b *SimulatedBackend) rollback(parent *types.Block) {
@@ -174,7 +181,7 @@ func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error {
// stateByBlockNumber retrieves a state by a given blocknumber.
func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) {
if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 {
if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 {
return b.blockchain.State()
}
block, err := b.blockByNumber(ctx, blockNumber)
@@ -193,6 +200,23 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address,
if err != nil {
return nil, err
}
return stateDB.GetCode(contract), nil
}
// CodeAtHash returns the code associated with a certain account in the blockchain.
func (b *SimulatedBackend) CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
header, err := b.headerByHash(blockHash)
if err != nil {
return nil, err
}
stateDB, err := b.blockchain.StateAt(header.Root)
if err != nil {
return nil, err
}
return stateDB.GetCode(contract), nil
}
@@ -206,7 +230,6 @@ func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Addres
if err != nil {
return nil, err
}
return stateDB.GetBalance(contract), nil
}
@@ -219,7 +242,6 @@ func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address,
if err != nil {
return 0, err
}
return stateDB.GetNonce(contract), nil
}
@@ -232,7 +254,6 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres
if err != nil {
return nil, err
}
val := stateDB.GetState(contract, key)
return val[:], nil
}
@@ -303,7 +324,7 @@ func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (
// (associated with its hash) if found without Lock.
func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 {
return b.blockchain.CurrentBlock(), nil
return b.blockByHash(ctx, b.blockchain.CurrentBlock().Hash())
}
block := b.blockchain.GetBlockByNumber(uint64(number.Int64()))
@@ -318,7 +339,11 @@ func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (
func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
b.mu.Lock()
defer b.mu.Unlock()
return b.headerByHash(hash)
}
// headerByHash retrieves a header from the database by hash without Lock.
func (b *SimulatedBackend) headerByHash(hash common.Hash) (*types.Header, error) {
if hash == b.pendingBlock.Hash() {
return b.pendingBlock.Header(), nil
}
@@ -431,9 +456,25 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
b.mu.Lock()
defer b.mu.Unlock()
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 {
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
return nil, errBlockNumberUnsupported
}
return b.callContractAtHead(ctx, call)
}
// CallContractAtHash executes a contract call on a specific block hash.
func (b *SimulatedBackend) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
if blockHash != b.blockchain.CurrentBlock().Hash() {
return nil, errBlockHashUnsupported
}
return b.callContractAtHead(ctx, call)
}
// callContractAtHead executes a contract call against the latest block state.
func (b *SimulatedBackend) callContractAtHead(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
stateDB, err := b.blockchain.State()
if err != nil {
return nil, err
@@ -455,7 +496,7 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereu
defer b.mu.Unlock()
defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
if err != nil {
return nil, err
}
@@ -549,7 +590,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
call.Gas = gas
snapshot := b.pendingState.Snapshot()
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
b.pendingState.RevertToSnapshot(snapshot)
if err != nil {
@@ -584,7 +625,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
return 0, err
}
if failed {
if result != nil && result.Err != vm.ErrOutOfGas {
if result != nil && !errors.Is(result.Err, vm.ErrOutOfGas) {
if len(result.Revert()) > 0 {
return 0, newRevertError(result)
}
@@ -599,13 +640,12 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// callContract implements common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) {
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, header *types.Header, stateDB *state.StateDB) (*core.ExecutionResult, error) {
// Gas prices post 1559 need to be initialized
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
head := b.blockchain.CurrentHeader()
if !b.blockchain.Config().IsLondon(head.Number) {
if !b.blockchain.Config().IsLondon(header.Number) {
// If there's no basefee, then it must be a non-1559 execution
if call.GasPrice == nil {
call.GasPrice = new(big.Int)
@@ -627,31 +667,44 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
call.GasPrice = new(big.Int)
if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap)
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap)
}
}
}
// Ensure message is initialized properly.
if call.Gas == 0 {
call.Gas = 50000000
call.Gas = 10 * header.GasLimit
}
if call.Value == nil {
call.Value = new(big.Int)
}
// Set infinite balance to the fake caller account.
from := stateDB.GetOrNewStateObject(call.From)
from.SetBalance(math.MaxBig256)
// Execute the call.
msg := callMsg{call}
txContext := core.NewEVMTxContext(msg)
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
// Execute the call.
msg := &core.Message{
From: call.From,
To: call.To,
Value: call.Value,
GasLimit: call.Gas,
GasPrice: call.GasPrice,
GasFeeCap: call.GasFeeCap,
GasTipCap: call.GasTipCap,
Data: call.Data,
AccessList: call.AccessList,
SkipAccountChecks: true,
}
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
txContext := core.NewEVMTxContext(msg)
evmContext := core.NewEVMBlockContext(header, b.blockchain, nil)
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb()
return core.ApplyMessage(vmEnv, msg, gasPool)
}
// SendTransaction updates the pending block to include the given transaction.
@@ -662,10 +715,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
// Get the last block
block, err := b.blockByHash(ctx, b.pendingBlock.ParentHash())
if err != nil {
return fmt.Errorf("could not fetch parent")
return errors.New("could not fetch parent")
}
// Check transaction validity
signer := types.MakeSigner(b.blockchain.Config(), block.Number())
signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time())
sender, err := types.Sender(signer, tx)
if err != nil {
return fmt.Errorf("invalid transaction: %v", err)
@@ -681,8 +734,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
}
block.AddTxWithChain(b.blockchain, tx)
})
stateDB, _ := b.blockchain.State()
stateDB, err := b.blockchain.State()
if err != nil {
return err
}
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
b.pendingReceipts = receipts[0]
@@ -791,22 +846,23 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
defer b.mu.Unlock()
if len(b.pendingBlock.Transactions()) != 0 {
return errors.New("Could not adjust time on non-empty block")
return errors.New("could not adjust time on non-empty block")
}
// Get the last block
block := b.blockchain.GetBlockByHash(b.pendingBlock.ParentHash())
if block == nil {
return fmt.Errorf("could not find parent")
return errors.New("could not find parent")
}
blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
block.OffsetTime(int64(adjustment.Seconds()))
})
stateDB, _ := b.blockchain.State()
stateDB, err := b.blockchain.State()
if err != nil {
return err
}
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
return nil
}
@@ -815,23 +871,6 @@ func (b *SimulatedBackend) Blockchain() *core.BlockChain {
return b.blockchain
}
// callMsg implements core.Message to allow passing it as a transaction simulator.
type callMsg struct {
ethereum.CallMsg
}
func (m callMsg) From() common.Address { return m.CallMsg.From }
func (m callMsg) Nonce() uint64 { return 0 }
func (m callMsg) IsFake() bool { return true }
func (m callMsg) To() *common.Address { return m.CallMsg.To }
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap }
func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap }
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }
// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
type filterBackend struct {
@@ -854,15 +893,9 @@ func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNum
case rpc.LatestBlockNumber:
return fb.bc.CurrentHeader(), nil
case rpc.FinalizedBlockNumber:
if block := fb.bc.CurrentFinalizedBlock(); block != nil {
return block.Header(), nil
}
return nil, errors.New("finalized block not found")
return fb.bc.CurrentFinalBlock(), nil
case rpc.SafeBlockNumber:
if block := fb.bc.CurrentSafeBlock(); block != nil {
return block.Header(), nil
}
return nil, errors.New("safe block not found")
return fb.bc.CurrentSafeBlock(), nil
default:
return fb.bc.GetHeaderByNumber(uint64(number.Int64())), nil
}
@@ -888,11 +921,15 @@ func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (typ
if number == nil {
return nil, nil
}
return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil
header := rawdb.ReadHeader(fb.db, hash, *number)
if header == nil {
return nil, nil
}
return rawdb.ReadReceipts(fb.db, hash, *number, header.Time, fb.bc.Config()), nil
}
func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
logs := rawdb.ReadLogs(fb.db, hash, number, fb.bc.Config())
logs := rawdb.ReadLogs(fb.db, hash, number)
return logs, nil
}

View File

@@ -38,6 +38,7 @@ import (
)
func TestSimulatedBackend(t *testing.T) {
t.Parallel()
var gasLimit uint64 = 8000029
key, _ := crypto.GenerateKey() // nolint: gosec
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
@@ -121,6 +122,7 @@ func simTestBackend(testAddr common.Address) *SimulatedBackend {
}
func TestNewSimulatedBackend(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
expectedBal := big.NewInt(10000000000000000)
sim := simTestBackend(testAddr)
@@ -142,6 +144,7 @@ func TestNewSimulatedBackend(t *testing.T) {
}
func TestAdjustTime(t *testing.T) {
t.Parallel()
sim := NewSimulatedBackend(
core.GenesisAlloc{}, 10000000,
)
@@ -159,8 +162,10 @@ func TestAdjustTime(t *testing.T) {
}
func TestNewAdjustTimeFail(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.blockchain.Stop()
// Create tx and send
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
@@ -201,6 +206,7 @@ func TestNewAdjustTimeFail(t *testing.T) {
}
func TestBalanceAt(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
expectedBal := big.NewInt(10000000000000000)
sim := simTestBackend(testAddr)
@@ -218,6 +224,7 @@ func TestBalanceAt(t *testing.T) {
}
func TestBlockByHash(t *testing.T) {
t.Parallel()
sim := NewSimulatedBackend(
core.GenesisAlloc{}, 10000000,
)
@@ -239,6 +246,7 @@ func TestBlockByHash(t *testing.T) {
}
func TestBlockByNumber(t *testing.T) {
t.Parallel()
sim := NewSimulatedBackend(
core.GenesisAlloc{}, 10000000,
)
@@ -274,6 +282,7 @@ func TestBlockByNumber(t *testing.T) {
}
func TestNonceAt(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -327,6 +336,7 @@ func TestNonceAt(t *testing.T) {
}
func TestSendTransaction(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -361,6 +371,7 @@ func TestSendTransaction(t *testing.T) {
}
func TestTransactionByHash(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := NewSimulatedBackend(
@@ -415,6 +426,7 @@ func TestTransactionByHash(t *testing.T) {
}
func TestEstimateGas(t *testing.T) {
t.Parallel()
/*
pragma solidity ^0.6.4;
contract GasEstimation {
@@ -534,6 +546,7 @@ func TestEstimateGas(t *testing.T) {
}
func TestEstimateGasWithPrice(t *testing.T) {
t.Parallel()
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
@@ -624,6 +637,7 @@ func TestEstimateGasWithPrice(t *testing.T) {
}
func TestHeaderByHash(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -645,6 +659,7 @@ func TestHeaderByHash(t *testing.T) {
}
func TestHeaderByNumber(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -691,6 +706,7 @@ func TestHeaderByNumber(t *testing.T) {
}
func TestTransactionCount(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -743,6 +759,7 @@ func TestTransactionCount(t *testing.T) {
}
func TestTransactionInBlock(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -808,6 +825,7 @@ func TestTransactionInBlock(t *testing.T) {
}
func TestPendingNonceAt(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -873,6 +891,7 @@ func TestPendingNonceAt(t *testing.T) {
}
func TestTransactionReceipt(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
@@ -907,6 +926,7 @@ func TestTransactionReceipt(t *testing.T) {
}
func TestSuggestGasPrice(t *testing.T) {
t.Parallel()
sim := NewSimulatedBackend(
core.GenesisAlloc{},
10000000,
@@ -923,6 +943,7 @@ func TestSuggestGasPrice(t *testing.T) {
}
func TestPendingCodeAt(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
@@ -959,6 +980,7 @@ func TestPendingCodeAt(t *testing.T) {
}
func TestCodeAt(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
@@ -995,10 +1017,49 @@ func TestCodeAt(t *testing.T) {
}
}
func TestCodeAtHash(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
bgCtx := context.Background()
code, err := sim.CodeAtHash(bgCtx, testAddr, sim.Blockchain().CurrentHeader().Hash())
if err != nil {
t.Errorf("could not get code at test addr: %v", err)
}
if len(code) != 0 {
t.Errorf("got code for account that does not have contract code")
}
parsed, err := abi.JSON(strings.NewReader(abiJSON))
if err != nil {
t.Errorf("could not get code at test addr: %v", err)
}
auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
if err != nil {
t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
}
blockHash := sim.Commit()
code, err = sim.CodeAtHash(bgCtx, contractAddr, blockHash)
if err != nil {
t.Errorf("could not get code at test addr: %v", err)
}
if len(code) == 0 {
t.Errorf("did not get code for account that has contract code")
}
// ensure code received equals code deployed
if !bytes.Equal(code, common.FromHex(deployedCode)) {
t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
}
}
// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
//
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
func TestPendingAndCallContract(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
@@ -1037,7 +1098,7 @@ func TestPendingAndCallContract(t *testing.T) {
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
}
sim.Commit()
blockHash := sim.Commit()
// make sure you can call the contract
res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
@@ -1055,6 +1116,23 @@ func TestPendingAndCallContract(t *testing.T) {
if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
}
// make sure you can call the contract by hash
res, err = sim.CallContractAtHash(bgCtx, ethereum.CallMsg{
From: testAddr,
To: &addr,
Data: input,
}, blockHash)
if err != nil {
t.Errorf("could not call receive method on contract: %v", err)
}
if len(res) == 0 {
t.Errorf("result of contract call was empty: %v", res)
}
if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
}
}
// This test is based on the following contract:
@@ -1083,6 +1161,7 @@ contract Reverter {
}
}*/
func TestCallContractRevert(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
@@ -1178,6 +1257,7 @@ func TestCallContractRevert(t *testing.T) {
// Since Commit() was called 2n+1 times in total,
// having a chain length of just n+1 means that a reorg occurred.
func TestFork(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
@@ -1189,7 +1269,7 @@ func TestFork(t *testing.T) {
sim.Commit()
}
// 3.
if sim.blockchain.CurrentBlock().NumberU64() != uint64(n) {
if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n) {
t.Error("wrong chain length")
}
// 4.
@@ -1199,7 +1279,7 @@ func TestFork(t *testing.T) {
sim.Commit()
}
// 6.
if sim.blockchain.CurrentBlock().NumberU64() != uint64(n+1) {
if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n+1) {
t.Error("wrong chain length")
}
}
@@ -1231,6 +1311,7 @@ const callableBin = "6080604052348015600f57600080fd5b5060998061001e6000396000f3f
// 9. Re-send the transaction and mine a block.
// 10. Check that the event was reborn.
func TestForkLogsReborn(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
@@ -1304,6 +1385,7 @@ func TestForkLogsReborn(t *testing.T) {
// 5. Mine a block, Re-send the transaction and mine another one.
// 6. Check that the TX is now included in block 2.
func TestForkResendTx(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
@@ -1340,11 +1422,12 @@ func TestForkResendTx(t *testing.T) {
}
func TestCommitReturnValue(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()
startBlockHeight := sim.blockchain.CurrentBlock().NumberU64()
startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64()
// Test if Commit returns the correct block hash
h1 := sim.Commit()
@@ -1381,6 +1464,7 @@ func TestCommitReturnValue(t *testing.T) {
// TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork
// block's parent rather than the canonical head's parent.
func TestAdjustTimeAfterFork(t *testing.T) {
t.Parallel()
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
defer sim.Close()

View File

@@ -34,6 +34,11 @@ import (
const basefeeWiggleMultiplier = 2
var (
errNoEventSignature = errors.New("no event signature")
errEventSignatureMismatch = errors.New("event signature mismatch")
)
// SignerFn is a signer function callback when a contract requires a method to
// sign the transaction before submission.
type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, error)
@@ -43,6 +48,7 @@ type CallOpts struct {
Pending bool // Whether to operate on the pending state or the last known one
From common.Address // Optional the sender address, otherwise the first account is used
BlockNumber *big.Int // Optional the block number on which the call should be performed
BlockHash common.Hash // Optional the block hash on which the call should be performed
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
@@ -184,6 +190,23 @@ func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method stri
return ErrNoCode
}
}
} else if opts.BlockHash != (common.Hash{}) {
bh, ok := c.caller.(BlockHashContractCaller)
if !ok {
return ErrNoBlockHashState
}
output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash)
if err != nil {
return err
}
if len(output) == 0 {
// Make sure we have a contract to operate on, and bail out otherwise.
if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil {
return err
} else if len(code) == 0 {
return ErrNoCode
}
}
} else {
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
if err != nil {
@@ -215,7 +238,7 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in
if err != nil {
return nil, err
}
// todo(rjl493456442) check the method is payable or not,
// todo(rjl493456442) check whether the method is payable or not,
// reject invalid transaction at the first place
return c.transact(opts, &c.address, input)
}
@@ -223,7 +246,7 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in
// RawTransact initiates a transaction with the given raw calldata as the input.
// It's usually used to initiate transactions for invoking **Fallback** function.
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
// todo(rjl493456442) check the method is payable or not,
// todo(rjl493456442) check whether the method is payable or not,
// reject invalid transaction at the first place
return c.transact(opts, &c.address, calldata)
}
@@ -488,8 +511,12 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
// UnpackLog unpacks a retrieved log into the provided output structure.
func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error {
// Anonymous events are not supported.
if len(log.Topics) == 0 {
return errNoEventSignature
}
if log.Topics[0] != c.abi.Events[event].ID {
return fmt.Errorf("event signature mismatch")
return errEventSignatureMismatch
}
if len(log.Data) > 0 {
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
@@ -507,8 +534,12 @@ func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log)
// UnpackLogIntoMap unpacks a retrieved log into the provided map.
func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event string, log types.Log) error {
// Anonymous events are not supported.
if len(log.Topics) == 0 {
return errNoEventSignature
}
if log.Topics[0] != c.abi.Events[event].ID {
return fmt.Errorf("event signature mismatch")
return errEventSignatureMismatch
}
if len(log.Data) > 0 {
if err := c.abi.UnpackIntoMap(out, event, log.Data); err != nil {

View File

@@ -114,7 +114,28 @@ func (mc *mockPendingCaller) PendingCallContract(ctx context.Context, call ether
return mc.pendingCallContractBytes, mc.pendingCallContractErr
}
type mockBlockHashCaller struct {
*mockCaller
codeAtHashBytes []byte
codeAtHashErr error
codeAtHashCalled bool
callContractAtHashCalled bool
callContractAtHashBytes []byte
callContractAtHashErr error
}
func (mc *mockBlockHashCaller) CodeAtHash(ctx context.Context, contract common.Address, hash common.Hash) ([]byte, error) {
mc.codeAtHashCalled = true
return mc.codeAtHashBytes, mc.codeAtHashErr
}
func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, hash common.Hash) ([]byte, error) {
mc.callContractAtHashCalled = true
return mc.callContractAtHashBytes, mc.callContractAtHashErr
}
func TestPassingBlockNumber(t *testing.T) {
t.Parallel()
mc := &mockPendingCaller{
mockCaller: &mockCaller{
codeAtBytes: []byte{1, 2, 3},
@@ -166,6 +187,7 @@ func TestPassingBlockNumber(t *testing.T) {
const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158"
func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) {
t.Parallel()
hash := crypto.Keccak256Hash([]byte("testName"))
topics := []common.Hash{
crypto.Keccak256Hash([]byte("received(string,address,uint256,bytes)")),
@@ -186,7 +208,26 @@ func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) {
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackAnonymousLogIntoMap(t *testing.T) {
t.Parallel()
mockLog := newMockLog(nil, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
var received map[string]interface{}
err := bc.UnpackLogIntoMap(received, "received", mockLog)
if err == nil {
t.Error("unpacking anonymous event is not supported")
}
if err.Error() != "no event signature" {
t.Errorf("expected error 'no event signature', got '%s'", err)
}
}
func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
t.Parallel()
sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"})
if err != nil {
t.Fatal(err)
@@ -212,6 +253,7 @@ func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
}
func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
t.Parallel()
arrBytes, err := rlp.EncodeToBytes([2]common.Address{common.HexToAddress("0x0"), common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")})
if err != nil {
t.Fatal(err)
@@ -237,6 +279,7 @@ func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
}
func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
t.Parallel()
mockAddress := common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")
addrBytes := mockAddress.Bytes()
hash := crypto.Keccak256Hash([]byte("mockFunction(address,uint)"))
@@ -263,6 +306,7 @@ func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
}
func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) {
t.Parallel()
bytes := []byte{1, 2, 3, 4, 5}
hash := crypto.Keccak256Hash(bytes)
topics := []common.Hash{
@@ -285,6 +329,7 @@ func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) {
}
func TestTransactGasFee(t *testing.T) {
t.Parallel()
assert := assert.New(t)
// GasTipCap and GasFeeCap
@@ -360,6 +405,7 @@ func newMockLog(topics []common.Hash, txHash common.Hash) types.Log {
}
func TestCall(t *testing.T) {
t.Parallel()
var method, methodWithArg = "something", "somethingArrrrg"
tests := []struct {
name, method string
@@ -383,6 +429,15 @@ func TestCall(t *testing.T) {
Pending: true,
},
method: method,
}, {
name: "ok hash",
mc: &mockBlockHashCaller{
codeAtHashBytes: []byte{0},
},
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
}, {
name: "pack error, no method",
mc: new(mockCaller),
@@ -396,6 +451,14 @@ func TestCall(t *testing.T) {
},
method: method,
wantErrExact: bind.ErrNoPendingState,
}, {
name: "interface error, blockHash but not a BlockHashContractCaller",
mc: new(mockCaller),
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErrExact: bind.ErrNoBlockHashState,
}, {
name: "pending call canceled",
mc: &mockPendingCaller{
@@ -443,6 +506,34 @@ func TestCall(t *testing.T) {
mc: new(mockCaller),
method: method,
wantErrExact: bind.ErrNoCode,
}, {
name: "call contract at hash error",
mc: &mockBlockHashCaller{
callContractAtHashErr: context.DeadlineExceeded,
},
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErrExact: context.DeadlineExceeded,
}, {
name: "code at error",
mc: &mockBlockHashCaller{
codeAtHashErr: errors.New(""),
},
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErr: true,
}, {
name: "no code at hash",
mc: new(mockBlockHashCaller),
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErrExact: bind.ErrNoCode,
}, {
name: "unpack error missing arg",
mc: &mockCaller{
@@ -490,6 +581,7 @@ func TestCall(t *testing.T) {
// TestCrashers contains some strings which previously caused the abi codec to crash.
func TestCrashers(t *testing.T) {
t.Parallel()
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`))
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"&"}]}]}]`))
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"----"}]}]}]`))

View File

@@ -79,7 +79,7 @@ func isKeyWord(arg string) bool {
// Bind generates a Go wrapper around a contract ABI. This wrapper isn't meant
// to be used as is in client code, but rather as an intermediate struct which
// enforces compile time type safety and naming convention opposed to having to
// enforces compile time type safety and naming convention as opposed to having to
// manually maintain hard coded strings that break on runtime.
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string) (string, error) {
var (
@@ -133,12 +133,19 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
// Normalize the method for capital cases and non-anonymous inputs/outputs
normalized := original
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
// Ensure there is no duplicated identifier
var identifiers = callIdentifiers
if !original.IsConstant() {
identifiers = transactIdentifiers
}
// Name shouldn't start with a digit. It will make the generated code invalid.
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
normalizedName = fmt.Sprintf("M%s", normalizedName)
normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool {
_, ok := identifiers[name]
return ok
})
}
if identifiers[normalizedName] {
return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName)
}
@@ -182,6 +189,14 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
// Ensure there is no duplicated identifier
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
// Name shouldn't start with a digit. It will make the generated code invalid.
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
normalizedName = fmt.Sprintf("E%s", normalizedName)
normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool {
_, ok := eventIdentifiers[name]
return ok
})
}
if eventIdentifiers[normalizedName] {
return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName)
}
@@ -348,7 +363,7 @@ func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
// parameters that are not value types i.e. arrays and structs are not
// stored directly but instead a keccak256-hash of an encoding is stored.
//
// We only convert stringS and bytes to hash, still need to deal with
// We only convert strings and bytes to hash, still need to deal with
// array(both fixed-size and dynamic-size) and struct.
if bound == "string" || bound == "[]byte" {
bound = "common.Hash"

View File

@@ -1677,7 +1677,7 @@ var bindTests = []struct {
}
sim.Commit()
// This test the existence of the free retreiver call for view and pure functions
// This test the existence of the free retriever call for view and pure functions
if num, err := pav.PureFunc(nil); err != nil {
t.Fatalf("Failed to call anonymous field retriever: %v", err)
} else if num.Cmp(big.NewInt(42)) != 0 {
@@ -2038,12 +2038,36 @@ var bindTests = []struct {
t.Errorf("error deploying the contract: %v", err)
}
`,
}, {
name: "NumericMethodName",
contract: `
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;
contract NumericMethodName {
event _1TestEvent(address _param);
function _1test() public pure {}
function __1test() public pure {}
function __2test() public pure {}
}
`,
bytecode: []string{"0x6080604052348015600f57600080fd5b5060958061001e6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80639d993132146041578063d02767c7146049578063ffa02795146051575b600080fd5b60476059565b005b604f605b565b005b6057605d565b005b565b565b56fea26469706673582212200382ca602dff96a7e2ba54657985e2b4ac423a56abe4a1f0667bc635c4d4371f64736f6c63430008110033"},
abi: []string{`[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_param","type":"address"}],"name":"_1TestEvent","type":"event"},{"inputs":[],"name":"_1test","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"__1test","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"__2test","outputs":[],"stateMutability":"pure","type":"function"}]`},
imports: `
"github.com/ethereum/go-ethereum/common"
`,
tester: `
if b, err := NewNumericMethodName(common.Address{}, nil); b == nil || err != nil {
t.Fatalf("combined binding (%v) nil or error (%v) not nil", b, nil)
}
`,
},
}
// Tests that packages generated by the binder can be successfully compiled and
// the requested tester run against it.
func TestGolangBindings(t *testing.T) {
t.Parallel()
// Skip the test if no Go command can be found
gocmd := runtime.GOROOT() + "/bin/go"
if !common.FileExist(gocmd) {

View File

@@ -325,7 +325,7 @@ var (
if err != nil {
return *outstruct, err
}
{{range $i, $t := .Normalized.Outputs}}
{{range $i, $t := .Normalized.Outputs}}
outstruct.{{.Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
return *outstruct, err
@@ -335,7 +335,7 @@ var (
}
{{range $i, $t := .Normalized.Outputs}}
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err
{{end}}
}
@@ -378,7 +378,7 @@ var (
}
{{end}}
{{if .Fallback}}
{{if .Fallback}}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
// Solidity: {{.Fallback.Original.String}}
@@ -392,16 +392,16 @@ var (
func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
//
// Solidity: {{.Fallback.Original.String}}
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
}
{{end}}
{{if .Receive}}
{{if .Receive}}
// Receive is a paid mutator transaction binding the contract receive function.
//
// Solidity: {{.Receive.Original.String}}
@@ -415,9 +415,9 @@ var (
func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
}
// Receive is a paid mutator transaction binding the contract receive function.
//
//
// Solidity: {{.Receive.Original.String}}
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)

View File

@@ -53,6 +53,7 @@ var waitDeployedTests = map[string]struct {
}
func TestWaitDeployed(t *testing.T) {
t.Parallel()
for name, test := range waitDeployedTests {
backend := backends.NewSimulatedBackend(
core.GenesisAlloc{
@@ -100,6 +101,7 @@ func TestWaitDeployed(t *testing.T) {
}
func TestWaitDeployedCornerCases(t *testing.T) {
t.Parallel()
backend := backends.NewSimulatedBackend(
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
@@ -119,9 +121,9 @@ func TestWaitDeployedCornerCases(t *testing.T) {
defer cancel()
backend.SendTransaction(ctx, tx)
backend.Commit()
notContentCreation := errors.New("tx is not contract creation")
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContentCreation.Error() {
t.Errorf("error missmatch: want %q, got %q, ", notContentCreation, err)
notContractCreation := errors.New("tx is not contract creation")
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContractCreation.Error() {
t.Errorf("error mismatch: want %q, got %q, ", notContractCreation, err)
}
// Create a transaction that is not mined.
@@ -131,7 +133,7 @@ func TestWaitDeployedCornerCases(t *testing.T) {
go func() {
contextCanceled := errors.New("context canceled")
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != contextCanceled.Error() {
t.Errorf("error missmatch: want %q, got %q, ", contextCanceled, err)
t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err)
}
}()

View File

@@ -18,7 +18,6 @@ package abi
import (
"bytes"
"errors"
"fmt"
"strings"
@@ -32,7 +31,7 @@ type Error struct {
str string
// Sig contains the string signature according to the ABI spec.
// e.g. error foo(uint32 a, int b) = "foo(uint32,int256)"
// e.g. error foo(uint32 a, int b) = "foo(uint32,int256)"
// Please note that "int" is substitute for its canonical representation "int256"
Sig string
@@ -78,16 +77,16 @@ func NewError(name string, inputs Arguments) Error {
}
}
func (e *Error) String() string {
func (e Error) String() string {
return e.str
}
func (e *Error) Unpack(data []byte) (interface{}, error) {
if len(data) < 4 {
return "", errors.New("invalid data for unpacking")
return "", fmt.Errorf("insufficient data for unpacking: have %d, want at least 4", len(data))
}
if !bytes.Equal(data[:4], e.ID[:4]) {
return "", errors.New("invalid data for unpacking")
return "", fmt.Errorf("invalid identifier, have %#x want %#x", data[:4], e.ID[:4])
}
return e.Inputs.Unpack(data[4:])
}

View File

@@ -81,6 +81,7 @@ var pledgeData1 = "00000000000000000000000000ce0d46d924cc8437c806721496599fc3ffa
var mixedCaseData1 = "00000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000020489e8000000000000000000000000000000000000000000000000000000000000000f4241"
func TestEventId(t *testing.T) {
t.Parallel()
var table = []struct {
definition string
expectations map[string]common.Hash
@@ -112,6 +113,7 @@ func TestEventId(t *testing.T) {
}
func TestEventString(t *testing.T) {
t.Parallel()
var table = []struct {
definition string
expectations map[string]string
@@ -146,6 +148,7 @@ func TestEventString(t *testing.T) {
// TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
func TestEventMultiValueWithArrayUnpack(t *testing.T) {
t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
abi, err := JSON(strings.NewReader(definition))
require.NoError(t, err)
@@ -161,6 +164,7 @@ func TestEventMultiValueWithArrayUnpack(t *testing.T) {
}
func TestEventTupleUnpack(t *testing.T) {
t.Parallel()
type EventTransfer struct {
Value *big.Int
}
@@ -351,6 +355,7 @@ func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, ass
// TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
func TestEventUnpackIndexed(t *testing.T) {
t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
type testStruct struct {
Value1 uint8 // indexed
@@ -368,6 +373,7 @@ func TestEventUnpackIndexed(t *testing.T) {
// TestEventIndexedWithArrayUnpack verifies that decoder will not overflow when static array is indexed input.
func TestEventIndexedWithArrayUnpack(t *testing.T) {
t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
type testStruct struct {
Value1 [2]uint8 // indexed

View File

@@ -117,24 +117,23 @@ func NewMethod(name string, rawName string, funType FunctionType, mutability str
sig = fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ","))
id = crypto.Keccak256([]byte(sig))[:4]
}
// Extract meaningful state mutability of solidity method.
// If it's default value, never print it.
state := mutability
if state == "nonpayable" {
state = ""
}
if state != "" {
state = state + " "
}
identity := fmt.Sprintf("function %v", rawName)
if funType == Fallback {
switch funType {
case Fallback:
identity = "fallback"
} else if funType == Receive {
case Receive:
identity = "receive"
} else if funType == Constructor {
case Constructor:
identity = "constructor"
}
str := fmt.Sprintf("%v(%v) %sreturns(%v)", identity, strings.Join(inputNames, ", "), state, strings.Join(outputNames, ", "))
var str string
// Extract meaningful state mutability of solidity method.
// If it's empty string or default value "nonpayable", never print it.
if mutability == "" || mutability == "nonpayable" {
str = fmt.Sprintf("%v(%v) returns(%v)", identity, strings.Join(inputNames, ", "), strings.Join(outputNames, ", "))
} else {
str = fmt.Sprintf("%v(%v) %s returns(%v)", identity, strings.Join(inputNames, ", "), mutability, strings.Join(outputNames, ", "))
}
return Method{
Name: name,

View File

@@ -35,6 +35,7 @@ const methoddata = `
]`
func TestMethodString(t *testing.T) {
t.Parallel()
var table = []struct {
method string
expectation string
@@ -84,11 +85,12 @@ func TestMethodString(t *testing.T) {
for _, test := range table {
var got string
if test.method == "fallback" {
switch test.method {
case "fallback":
got = abi.Fallback.String()
} else if test.method == "receive" {
case "receive":
got = abi.Receive.String()
} else {
default:
got = abi.Methods[test.method].String()
}
if got != test.expectation {
@@ -98,6 +100,7 @@ func TestMethodString(t *testing.T) {
}
func TestMethodSig(t *testing.T) {
t.Parallel()
var cases = []struct {
method string
expect string

View File

@@ -57,7 +57,7 @@ func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
reflectValue = mustArrayToByteSlice(reflectValue)
}
if reflectValue.Type() != reflect.TypeOf([]byte{}) {
return []byte{}, errors.New("Bytes type is neither slice nor array")
return []byte{}, errors.New("bytes type is neither slice nor array")
}
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()), nil
case FixedBytesTy, FunctionTy:
@@ -66,7 +66,7 @@ func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
}
return common.RightPadBytes(reflectValue.Bytes(), 32), nil
default:
return []byte{}, fmt.Errorf("Could not pack element, unknown type: %v", t.T)
return []byte{}, fmt.Errorf("could not pack element, unknown type: %v", t.T)
}
}

View File

@@ -32,8 +32,11 @@ import (
// TestPack tests the general pack/unpack tests in packing_test.go
func TestPack(t *testing.T) {
t.Parallel()
for i, test := range packUnpackTests {
i, test := i, test
t.Run(strconv.Itoa(i), func(t *testing.T) {
t.Parallel()
encb, err := hex.DecodeString(test.packed)
if err != nil {
t.Fatalf("invalid hex %s: %v", test.packed, err)
@@ -57,6 +60,7 @@ func TestPack(t *testing.T) {
}
func TestMethodPack(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -177,6 +181,7 @@ func TestMethodPack(t *testing.T) {
}
func TestPackNumber(t *testing.T) {
t.Parallel()
tests := []struct {
value reflect.Value
packed []byte

View File

@@ -134,7 +134,7 @@ func setSlice(dst, src reflect.Value) error {
dst.Set(slice)
return nil
}
return errors.New("Cannot set slice, destination not settable")
return errors.New("cannot set slice, destination not settable")
}
func setArray(dst, src reflect.Value) error {
@@ -155,7 +155,7 @@ func setArray(dst, src reflect.Value) error {
dst.Set(array)
return nil
}
return errors.New("Cannot set array, destination not settable")
return errors.New("cannot set array, destination not settable")
}
func setStruct(dst, src reflect.Value) error {
@@ -163,7 +163,7 @@ func setStruct(dst, src reflect.Value) error {
srcField := src.Field(i)
dstField := dst.Field(i)
if !dstField.IsValid() || !srcField.IsValid() {
return fmt.Errorf("Could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
return fmt.Errorf("could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
}
if err := set(dstField, srcField); err != nil {
return err
@@ -228,7 +228,7 @@ func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[stri
structFieldName := ToCamelCase(argName)
if structFieldName == "" {
return nil, fmt.Errorf("abi: purely underscored output cannot unpack to struct")
return nil, errors.New("abi: purely underscored output cannot unpack to struct")
}
// this abi has already been paired, skip it... unless there exists another, yet unassigned

View File

@@ -170,8 +170,11 @@ var reflectTests = []reflectTest{
}
func TestReflectNameToStruct(t *testing.T) {
t.Parallel()
for _, test := range reflectTests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
if len(test.err) > 0 {
if err == nil || err.Error() != test.err {
@@ -192,6 +195,7 @@ func TestReflectNameToStruct(t *testing.T) {
}
func TestConvertType(t *testing.T) {
t.Parallel()
// Test Basic Struct
type T struct {
X *big.Int

View File

@@ -17,6 +17,7 @@
package abi
import (
"errors"
"fmt"
)
@@ -40,7 +41,7 @@ func isIdentifierSymbol(c byte) bool {
func parseToken(unescapedSelector string, isIdent bool) (string, string, error) {
if len(unescapedSelector) == 0 {
return "", "", fmt.Errorf("empty token")
return "", "", errors.New("empty token")
}
firstChar := unescapedSelector[0]
position := 1
@@ -110,7 +111,7 @@ func parseCompositeType(unescapedSelector string) ([]interface{}, string, error)
func parseType(unescapedSelector string) (interface{}, string, error) {
if len(unescapedSelector) == 0 {
return nil, "", fmt.Errorf("empty type")
return nil, "", errors.New("empty type")
}
if unescapedSelector[0] == '(' {
return parseCompositeType(unescapedSelector)

View File

@@ -24,6 +24,7 @@ import (
)
func TestParseSelector(t *testing.T) {
t.Parallel()
mkType := func(types ...interface{}) []ArgumentMarshaling {
var result []ArgumentMarshaling
for i, typeOrComponents := range types {

View File

@@ -75,7 +75,7 @@ func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
copy(topic[:], hash[:])
default:
// todo(rjl493456442) according solidity documentation, indexed event
// todo(rjl493456442) according to solidity documentation, indexed event
// parameters that are not value types i.e. arrays and structs are not
// stored directly but instead a keccak256-hash of an encoding is stored.
//

View File

@@ -26,6 +26,7 @@ import (
)
func TestMakeTopics(t *testing.T) {
t.Parallel()
type args struct {
query [][]interface{}
}
@@ -117,7 +118,9 @@ func TestMakeTopics(t *testing.T) {
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := MakeTopics(tt.args.query...)
if (err != nil) != tt.wantErr {
t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr)
@@ -347,10 +350,13 @@ func setupTopicsTests() []topicTest {
}
func TestParseTopics(t *testing.T) {
t.Parallel()
tests := setupTopicsTests()
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
createObj := tt.args.createObj()
if err := ParseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr)
@@ -364,10 +370,13 @@ func TestParseTopics(t *testing.T) {
}
func TestParseTopicsIntoMap(t *testing.T) {
t.Parallel()
tests := setupTopicsTests()
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
outMap := make(map[string]interface{})
if err := ParseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr)

View File

@@ -70,7 +70,7 @@ var (
func NewType(t string, internalType string, components []ArgumentMarshaling) (typ Type, err error) {
// check that array brackets are equal if they exist
if strings.Count(t, "[") != strings.Count(t, "]") {
return Type{}, fmt.Errorf("invalid arg type in abi")
return Type{}, errors.New("invalid arg type in abi")
}
typ.stringKind = t
@@ -109,7 +109,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
}
typ.stringKind = embeddedType.stringKind + sliced
} else {
return Type{}, fmt.Errorf("invalid formatting of array type")
return Type{}, errors.New("invalid formatting of array type")
}
return typ, err
}
@@ -348,7 +348,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
}
}
// requireLengthPrefix returns whether the type requires any sort of length
// requiresLengthPrefix returns whether the type requires any sort of length
// prefixing.
func (t Type) requiresLengthPrefix() bool {
return t.T == StringTy || t.T == BytesTy || t.T == SliceTy

View File

@@ -31,6 +31,7 @@ type typeWithoutStringer Type
// Tests that all allowed types get recognized by the type parser.
func TestTypeRegexp(t *testing.T) {
t.Parallel()
tests := []struct {
blob string
components []ArgumentMarshaling
@@ -117,6 +118,7 @@ func TestTypeRegexp(t *testing.T) {
}
func TestTypeCheck(t *testing.T) {
t.Parallel()
for i, test := range []struct {
typ string
components []ArgumentMarshaling
@@ -308,6 +310,7 @@ func TestTypeCheck(t *testing.T) {
}
func TestInternalType(t *testing.T) {
t.Parallel()
components := []ArgumentMarshaling{{Name: "a", Type: "int64"}}
internalType := "struct a.b[]"
kind := Type{
@@ -332,6 +335,7 @@ func TestInternalType(t *testing.T) {
}
func TestGetTypeSize(t *testing.T) {
t.Parallel()
var testCases = []struct {
typ string
components []ArgumentMarshaling
@@ -368,6 +372,7 @@ func TestGetTypeSize(t *testing.T) {
}
func TestNewFixedBytesOver32(t *testing.T) {
t.Parallel()
_, err := NewType("bytes4096", "", nil)
if err == nil {
t.Errorf("fixed bytes with size over 32 is not spec'd")

View File

@@ -18,6 +18,7 @@ package abi
import (
"encoding/binary"
"errors"
"fmt"
"math"
"math/big"
@@ -125,7 +126,7 @@ func readBool(word []byte) (bool, error) {
// readFunctionType enforces that standard by always presenting it as a 24-array (address + sig = 24 bytes)
func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) {
if t.T != FunctionTy {
return [24]byte{}, fmt.Errorf("abi: invalid type in call to make function type byte array")
return [24]byte{}, errors.New("abi: invalid type in call to make function type byte array")
}
if garbage := binary.BigEndian.Uint64(word[24:32]); garbage != 0 {
err = fmt.Errorf("abi: got improperly encoded function type, got %v", word)
@@ -138,7 +139,7 @@ func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) {
// ReadFixedBytes uses reflection to create a fixed array to be read from.
func ReadFixedBytes(t Type, word []byte) (interface{}, error) {
if t.T != FixedBytesTy {
return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array")
return nil, errors.New("abi: invalid type in call to make fixed byte array")
}
// convert
array := reflect.New(t.GetType()).Elem()
@@ -159,14 +160,15 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
// this value will become our slice or our array, depending on the type
var refSlice reflect.Value
if t.T == SliceTy {
switch t.T {
case SliceTy:
// declare our slice
refSlice = reflect.MakeSlice(t.GetType(), size, size)
} else if t.T == ArrayTy {
case ArrayTy:
// declare our array
refSlice = reflect.New(t.GetType()).Elem()
} else {
return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage")
default:
return nil, errors.New("abi: invalid type in array/slice unpacking stage")
}
// Arrays have packed elements, resulting in longer unpack steps.

View File

@@ -33,6 +33,7 @@ import (
// TestUnpack tests the general pack/unpack tests in packing_test.go
func TestUnpack(t *testing.T) {
t.Parallel()
for i, test := range packUnpackTests {
t.Run(strconv.Itoa(i)+" "+test.def, func(t *testing.T) {
//Unpack
@@ -206,13 +207,13 @@ var unpackTests = []unpackTest{
def: `[{"type":"bool"}]`,
enc: "",
want: false,
err: "abi: attempting to unmarshall an empty string while arguments are expected",
err: "abi: attempting to unmarshal an empty string while arguments are expected",
},
{
def: `[{"type":"bytes32","indexed":true},{"type":"uint256","indexed":false}]`,
enc: "",
want: false,
err: "abi: attempting to unmarshall an empty string while arguments are expected",
err: "abi: attempting to unmarshal an empty string while arguments are expected",
},
{
def: `[{"type":"bool","indexed":true},{"type":"uint64","indexed":true}]`,
@@ -224,6 +225,7 @@ var unpackTests = []unpackTest{
// TestLocalUnpackTests runs test specially designed only for unpacking.
// All test cases that can be used to test packing and unpacking should move to packing_test.go
func TestLocalUnpackTests(t *testing.T) {
t.Parallel()
for i, test := range unpackTests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
//Unpack
@@ -251,6 +253,7 @@ func TestLocalUnpackTests(t *testing.T) {
}
func TestUnpackIntoInterfaceSetDynamicArrayOutput(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(`[{"constant":true,"inputs":[],"name":"testDynamicFixedBytes15","outputs":[{"name":"","type":"bytes15[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"testDynamicFixedBytes32","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]`))
if err != nil {
t.Fatal(err)
@@ -321,6 +324,7 @@ func methodMultiReturn(require *require.Assertions) (ABI, []byte, methodMultiOut
}
func TestMethodMultiReturn(t *testing.T) {
t.Parallel()
type reversed struct {
String string
Int *big.Int
@@ -400,6 +404,7 @@ func TestMethodMultiReturn(t *testing.T) {
}
func TestMultiReturnWithArray(t *testing.T) {
t.Parallel()
const definition = `[{"name" : "multi", "type": "function", "outputs": [{"type": "uint64[3]"}, {"type": "uint64"}]}]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
@@ -423,6 +428,7 @@ func TestMultiReturnWithArray(t *testing.T) {
}
func TestMultiReturnWithStringArray(t *testing.T) {
t.Parallel()
const definition = `[{"name" : "multi", "type": "function", "outputs": [{"name": "","type": "uint256[3]"},{"name": "","type": "address"},{"name": "","type": "string[2]"},{"name": "","type": "bool"}]}]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
@@ -453,6 +459,7 @@ func TestMultiReturnWithStringArray(t *testing.T) {
}
func TestMultiReturnWithStringSlice(t *testing.T) {
t.Parallel()
const definition = `[{"name" : "multi", "type": "function", "outputs": [{"name": "","type": "string[]"},{"name": "","type": "uint256[]"}]}]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
@@ -485,6 +492,7 @@ func TestMultiReturnWithStringSlice(t *testing.T) {
}
func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
t.Parallel()
// Similar to TestMultiReturnWithArray, but with a special case in mind:
// values of nested static arrays count towards the size as well, and any element following
// after such nested array argument should be read with the correct offset,
@@ -525,6 +533,7 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
}
func TestUnmarshal(t *testing.T) {
t.Parallel()
const definition = `[
{ "name" : "int", "type": "function", "outputs": [ { "type": "uint256" } ] },
{ "name" : "bool", "type": "function", "outputs": [ { "type": "bool" } ] },
@@ -774,6 +783,7 @@ func TestUnmarshal(t *testing.T) {
}
func TestUnpackTuple(t *testing.T) {
t.Parallel()
const simpleTuple = `[{"name":"tuple","type":"function","outputs":[{"type":"tuple","name":"ret","components":[{"type":"int256","name":"a"},{"type":"int256","name":"b"}]}]}]`
abi, err := JSON(strings.NewReader(simpleTuple))
if err != nil {
@@ -876,6 +886,7 @@ func TestUnpackTuple(t *testing.T) {
}
func TestOOMMaliciousInput(t *testing.T) {
t.Parallel()
oomTests := []unpackTest{
{
def: `[{"type": "uint8[]"}]`,
@@ -946,6 +957,7 @@ func TestOOMMaliciousInput(t *testing.T) {
}
func TestPackAndUnpackIncompatibleNumber(t *testing.T) {
t.Parallel()
var encodeABI Arguments
uint256Ty, err := NewType("uint256", "", nil)
if err != nil {

View File

@@ -24,6 +24,7 @@ import (
)
func TestTextHash(t *testing.T) {
t.Parallel()
hash := TextHash([]byte("Hello Joe"))
want := hexutil.MustDecode("0xa080337ae51c4e064c189e113edd0ba391df9206e2f49db658bb32cf2911730b")
if !bytes.Equal(hash, want) {

View File

@@ -17,6 +17,7 @@
package external
import (
"errors"
"fmt"
"math/big"
"sync"
@@ -98,11 +99,11 @@ func (api *ExternalSigner) Status() (string, error) {
}
func (api *ExternalSigner) Open(passphrase string) error {
return fmt.Errorf("operation not supported on external signers")
return errors.New("operation not supported on external signers")
}
func (api *ExternalSigner) Close() error {
return fmt.Errorf("operation not supported on external signers")
return errors.New("operation not supported on external signers")
}
func (api *ExternalSigner) Accounts() []accounts.Account {
@@ -145,7 +146,7 @@ func (api *ExternalSigner) Contains(account accounts.Account) bool {
}
func (api *ExternalSigner) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) {
return accounts.Account{}, fmt.Errorf("operation not supported on external signers")
return accounts.Account{}, errors.New("operation not supported on external signers")
}
func (api *ExternalSigner) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) {
@@ -242,14 +243,14 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
}
func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
return []byte{}, fmt.Errorf("password-operations not supported on external signers")
return []byte{}, errors.New("password-operations not supported on external signers")
}
func (api *ExternalSigner) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
return nil, fmt.Errorf("password-operations not supported on external signers")
return nil, errors.New("password-operations not supported on external signers")
}
func (api *ExternalSigner) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) {
return nil, fmt.Errorf("password-operations not supported on external signers")
return nil, errors.New("password-operations not supported on external signers")
}
func (api *ExternalSigner) listAccounts() ([]common.Address, error) {

View File

@@ -25,6 +25,7 @@ import (
// Tests that HD derivation paths can be correctly parsed into our internal binary
// representation.
func TestHDPathParsing(t *testing.T) {
t.Parallel()
tests := []struct {
input string
output DerivationPath
@@ -89,6 +90,7 @@ func testDerive(t *testing.T, next func() DerivationPath, expected []string) {
}
func TestHdPathIteration(t *testing.T) {
t.Parallel()
testDerive(t, DefaultIterator(DefaultBaseDerivationPath),
[]string{
"m/44'/60'/0'/0/0", "m/44'/60'/0'/0/1",

View File

@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"golang.org/x/exp/slices"
)
// Minimum amount of time between cache reloads. This limit applies if the platform does
@@ -38,11 +39,10 @@ import (
// exist yet, the code will attempt to create a watcher at most this often.
const minReloadInterval = 2 * time.Second
type accountsByURL []accounts.Account
func (s accountsByURL) Len() int { return len(s) }
func (s accountsByURL) Less(i, j int) bool { return s[i].URL.Cmp(s[j].URL) < 0 }
func (s accountsByURL) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// byURL defines the sorting order for accounts.
func byURL(a, b accounts.Account) int {
return a.URL.Cmp(b.URL)
}
// AmbiguousAddrError is returned when attempting to unlock
// an address for which more than one file exists.
@@ -67,7 +67,7 @@ type accountCache struct {
keydir string
watcher *watcher
mu sync.Mutex
all accountsByURL
all []accounts.Account
byAddr map[common.Address][]accounts.Account
throttle *time.Timer
notify chan struct{}
@@ -194,7 +194,7 @@ func (ac *accountCache) find(a accounts.Account) (accounts.Account, error) {
default:
err := &AmbiguousAddrError{Addr: a.Address, Matches: make([]accounts.Account, len(matches))}
copy(err.Matches, matches)
sort.Sort(accountsByURL(err.Matches))
slices.SortFunc(err.Matches, byURL)
return accounts.Account{}, err
}
}

View File

@@ -17,12 +17,12 @@
package keystore
import (
"errors"
"fmt"
"math/rand"
"os"
"path/filepath"
"reflect"
"sort"
"testing"
"time"
@@ -30,6 +30,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"golang.org/x/exp/slices"
)
var (
@@ -67,14 +68,14 @@ func waitWatcherStart(ks *KeyStore) bool {
func waitForAccounts(wantAccounts []accounts.Account, ks *KeyStore) error {
var list []accounts.Account
for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(200 * time.Millisecond) {
for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(100 * time.Millisecond) {
list = ks.Accounts()
if reflect.DeepEqual(list, wantAccounts) {
// ks should have also received change notifications
select {
case <-ks.changes:
default:
return fmt.Errorf("wasn't notified of new accounts")
return errors.New("wasn't notified of new accounts")
}
return nil
}
@@ -113,7 +114,6 @@ func TestWatchNewFile(t *testing.T) {
func TestWatchNoDir(t *testing.T) {
t.Parallel()
// Create ks but not the directory that it watches.
rand.Seed(time.Now().UnixNano())
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int()))
ks := NewKeyStore(dir, LightScryptN, LightScryptP)
list := ks.Accounts()
@@ -152,6 +152,7 @@ func TestWatchNoDir(t *testing.T) {
}
func TestCacheInitialReload(t *testing.T) {
t.Parallel()
cache, _ := newAccountCache(cachetestDir)
accounts := cache.accounts()
if !reflect.DeepEqual(accounts, cachetestAccounts) {
@@ -160,6 +161,7 @@ func TestCacheInitialReload(t *testing.T) {
}
func TestCacheAddDeleteOrder(t *testing.T) {
t.Parallel()
cache, _ := newAccountCache("testdata/no-such-dir")
cache.watcher.running = true // prevent unexpected reloads
@@ -203,7 +205,7 @@ func TestCacheAddDeleteOrder(t *testing.T) {
// Check that the account list is sorted by filename.
wantAccounts := make([]accounts.Account, len(accs))
copy(wantAccounts, accs)
sort.Sort(accountsByURL(wantAccounts))
slices.SortFunc(wantAccounts, byURL)
list := cache.accounts()
if !reflect.DeepEqual(list, wantAccounts) {
t.Fatalf("got accounts: %s\nwant %s", spew.Sdump(accs), spew.Sdump(wantAccounts))
@@ -244,6 +246,7 @@ func TestCacheAddDeleteOrder(t *testing.T) {
}
func TestCacheFind(t *testing.T) {
t.Parallel()
dir := filepath.Join("testdata", "dir")
cache, _ := newAccountCache(dir)
cache.watcher.running = true // prevent unexpected reloads
@@ -322,7 +325,6 @@ func TestUpdatedKeyfileContents(t *testing.T) {
t.Parallel()
// Create a temporary keystore to test with
rand.Seed(time.Now().UnixNano())
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int()))
ks := NewKeyStore(dir, LightScryptN, LightScryptP)
@@ -351,7 +353,7 @@ func TestUpdatedKeyfileContents(t *testing.T) {
return
}
// needed so that modTime of `file` is different to its current value after forceCopyFile
time.Sleep(time.Second)
os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second))
// Now replace file contents
if err := forceCopyFile(file, cachetestAccounts[1].URL.Path); err != nil {
@@ -367,7 +369,7 @@ func TestUpdatedKeyfileContents(t *testing.T) {
}
// needed so that modTime of `file` is different to its current value after forceCopyFile
time.Sleep(time.Second)
os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second))
// Now replace file contents again
if err := forceCopyFile(file, cachetestAccounts[2].URL.Path); err != nil {
@@ -383,7 +385,7 @@ func TestUpdatedKeyfileContents(t *testing.T) {
}
// needed so that modTime of `file` is different to its current value after os.WriteFile
time.Sleep(time.Second)
os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second))
// Now replace file contents with crap
if err := os.WriteFile(file, []byte("foo"), 0600); err != nil {

View File

@@ -0,0 +1,34 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package keystore
import (
"testing"
)
func FuzzPassword(f *testing.F) {
f.Fuzz(func(t *testing.T, password string) {
ks := NewKeyStore(t.TempDir(), LightScryptN, LightScryptP)
a, err := ks.NewAccount(password)
if err != nil {
t.Fatal(err)
}
if err := ks.Unlock(a, password); err != nil {
t.Fatal(err)
}
})
}

View File

@@ -20,7 +20,6 @@ import (
"math/rand"
"os"
"runtime"
"sort"
"strings"
"sync"
"sync/atomic"
@@ -31,11 +30,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
"golang.org/x/exp/slices"
)
var testSigData = make([]byte, 32)
func TestKeyStore(t *testing.T) {
t.Parallel()
dir, ks := tmpKeyStore(t, true)
a, err := ks.NewAccount("foo")
@@ -70,6 +71,7 @@ func TestKeyStore(t *testing.T) {
}
func TestSign(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStore(t, true)
pass := "" // not used but required by API
@@ -86,6 +88,7 @@ func TestSign(t *testing.T) {
}
func TestSignWithPassphrase(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStore(t, true)
pass := "passwd"
@@ -280,6 +283,7 @@ type walletEvent struct {
// Tests that wallet notifications and correctly fired when accounts are added
// or deleted from the keystore.
func TestWalletNotifications(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStore(t, false)
// Subscribe to the wallet feed and collect events.
@@ -341,6 +345,7 @@ func TestWalletNotifications(t *testing.T) {
// TestImportExport tests the import functionality of a keystore.
func TestImportECDSA(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStore(t, true)
key, err := crypto.GenerateKey()
if err != nil {
@@ -359,6 +364,7 @@ func TestImportECDSA(t *testing.T) {
// TestImportECDSA tests the import and export functionality of a keystore.
func TestImportExport(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStore(t, true)
acc, err := ks.NewAccount("old")
if err != nil {
@@ -387,6 +393,7 @@ func TestImportExport(t *testing.T) {
// TestImportRace tests the keystore on races.
// This test should fail under -race if importing races.
func TestImportRace(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStore(t, true)
acc, err := ks.NewAccount("old")
if err != nil {
@@ -397,19 +404,19 @@ func TestImportRace(t *testing.T) {
t.Fatalf("failed to export account: %v", acc)
}
_, ks2 := tmpKeyStore(t, true)
var atom uint32
var atom atomic.Uint32
var wg sync.WaitGroup
wg.Add(2)
for i := 0; i < 2; i++ {
go func() {
defer wg.Done()
if _, err := ks2.Import(json, "new", "new"); err != nil {
atomic.AddUint32(&atom, 1)
atom.Add(1)
}
}()
}
wg.Wait()
if atom != 1 {
if atom.Load() != 1 {
t.Errorf("Import is racy")
}
}
@@ -424,7 +431,7 @@ func checkAccounts(t *testing.T, live map[common.Address]accounts.Account, walle
for _, account := range live {
liveList = append(liveList, account)
}
sort.Sort(accountsByURL(liveList))
slices.SortFunc(liveList, byURL)
for j, wallet := range wallets {
if accs := wallet.Accounts(); len(accs) != 1 {
t.Errorf("wallet %d: contains invalid number of accounts: have %d, want 1", j, len(accs))

View File

@@ -225,10 +225,13 @@ func DecryptKey(keyjson []byte, auth string) (*Key, error) {
if err != nil {
return nil, err
}
key := crypto.ToECDSAUnsafe(keyBytes)
key, err := crypto.ToECDSA(keyBytes)
if err != nil {
return nil, fmt.Errorf("invalid key: %w", err)
}
id, err := uuid.FromBytes(keyId)
if err != nil {
return nil, err
return nil, fmt.Errorf("invalid UUID: %w", err)
}
return &Key{
Id: id,

View File

@@ -30,6 +30,7 @@ const (
// Tests that a json key file can be decrypted and encrypted in multiple rounds.
func TestKeyEncryptDecrypt(t *testing.T) {
t.Parallel()
keyjson, err := os.ReadFile("testdata/very-light-scrypt.json")
if err != nil {
t.Fatal(err)
@@ -54,7 +55,7 @@ func TestKeyEncryptDecrypt(t *testing.T) {
// Recrypt with a new password and start over
password += "new data appended" // nolint: gosec
if keyjson, err = EncryptKey(key, password, veryLightScryptN, veryLightScryptP); err != nil {
t.Errorf("test %d: failed to recrypt key %v", i, err)
t.Errorf("test %d: failed to re-encrypt key %v", i, err)
}
}
}

View File

@@ -40,6 +40,7 @@ func tmpKeyStoreIface(t *testing.T, encrypted bool) (dir string, ks keyStore) {
}
func TestKeyStorePlain(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStoreIface(t, false)
pass := "" // not used but required by API
@@ -60,6 +61,7 @@ func TestKeyStorePlain(t *testing.T) {
}
func TestKeyStorePassphrase(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStoreIface(t, true)
pass := "foo"
@@ -80,6 +82,7 @@ func TestKeyStorePassphrase(t *testing.T) {
}
func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
t.Parallel()
_, ks := tmpKeyStoreIface(t, true)
pass := "foo"
@@ -93,6 +96,7 @@ func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
}
func TestImportPreSaleKey(t *testing.T) {
t.Parallel()
dir, ks := tmpKeyStoreIface(t, true)
// file content of a presale key file generated with:

View File

@@ -20,6 +20,7 @@
package keystore
import (
"os"
"time"
"github.com/ethereum/go-ethereum/log"
@@ -77,7 +78,9 @@ func (w *watcher) loop() {
}
defer watcher.Close()
if err := watcher.Add(w.ac.keydir); err != nil {
logger.Warn("Failed to watch keystore folder", "err", err)
if !os.IsNotExist(err) {
logger.Warn("Failed to watch keystore folder", "err", err)
}
return
}
@@ -122,7 +125,7 @@ func (w *watcher) loop() {
if !ok {
return
}
log.Info("Filsystem watcher error", "err", err)
log.Info("Filesystem watcher error", "err", err)
case <-debounce.C:
w.ac.scanAccounts()
rescanTriggered = false

View File

@@ -8,7 +8,7 @@
## Preparing the smartcard
**WARNING: FOILLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS**
**WARNING: FOLLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS**
You can use status' [keycard-cli](https://github.com/status-im/keycard-cli) and you should get _at least_ version 2.1.1 of their [smartcard application](https://github.com/status-im/status-keycard/releases/download/2.2.1/keycard_v2.2.1.cap)

View File

@@ -24,6 +24,7 @@ import (
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
@@ -125,7 +126,7 @@ func (s *SecureChannelSession) Pair(pairingPassword []byte) error {
// Unpair disestablishes an existing pairing.
func (s *SecureChannelSession) Unpair() error {
if s.PairingKey == nil {
return fmt.Errorf("cannot unpair: not paired")
return errors.New("cannot unpair: not paired")
}
_, err := s.transmitEncrypted(claSCWallet, insUnpair, s.PairingIndex, 0, []byte{})
@@ -141,7 +142,7 @@ func (s *SecureChannelSession) Unpair() error {
// Open initializes the secure channel.
func (s *SecureChannelSession) Open() error {
if s.iv != nil {
return fmt.Errorf("session already opened")
return errors.New("session already opened")
}
response, err := s.open()
@@ -215,7 +216,7 @@ func (s *SecureChannelSession) pair(p1 uint8, data []byte) (*responseAPDU, error
// transmitEncrypted sends an encrypted message, and decrypts and returns the response.
func (s *SecureChannelSession) transmitEncrypted(cla, ins, p1, p2 byte, data []byte) (*responseAPDU, error) {
if s.iv == nil {
return nil, fmt.Errorf("channel not open")
return nil, errors.New("channel not open")
}
data, err := s.encryptAPDU(data)
@@ -254,7 +255,7 @@ func (s *SecureChannelSession) transmitEncrypted(cla, ins, p1, p2 byte, data []b
return nil, err
}
if !bytes.Equal(s.iv, rmac) {
return nil, fmt.Errorf("invalid MAC in response")
return nil, errors.New("invalid MAC in response")
}
rapdu := &responseAPDU{}
@@ -319,7 +320,7 @@ func unpad(data []byte, terminator byte) ([]byte, error) {
return nil, fmt.Errorf("expected end of padding, got %d", data[len(data)-i])
}
}
return nil, fmt.Errorf("expected end of padding, got 0")
return nil, errors.New("expected end of padding, got 0")
}
// updateIV is an internal method that updates the initialization vector after

View File

@@ -252,7 +252,7 @@ func (w *Wallet) release() error {
// with the wallet.
func (w *Wallet) pair(puk []byte) error {
if w.session.paired() {
return fmt.Errorf("wallet already paired")
return errors.New("wallet already paired")
}
pairing, err := w.session.pair(puk)
if err != nil {
@@ -776,16 +776,16 @@ func (w *Wallet) findAccountPath(account accounts.Account) (accounts.DerivationP
return nil, fmt.Errorf("scheme %s does not match wallet scheme %s", account.URL.Scheme, w.Hub.scheme)
}
parts := strings.SplitN(account.URL.Path, "/", 2)
if len(parts) != 2 {
url, path, found := strings.Cut(account.URL.Path, "/")
if !found {
return nil, fmt.Errorf("invalid URL format: %s", account.URL)
}
if parts[0] != fmt.Sprintf("%x", w.PublicKey[1:3]) {
if url != fmt.Sprintf("%x", w.PublicKey[1:3]) {
return nil, fmt.Errorf("URL %s is not for this wallet", account.URL)
}
return accounts.ParseDerivationPath(parts[1])
return accounts.ParseDerivationPath(path)
}
// Session represents a secured communication session with the wallet.
@@ -813,7 +813,7 @@ func (s *Session) pair(secret []byte) (smartcardPairing, error) {
// unpair deletes an existing pairing.
func (s *Session) unpair() error {
if !s.verified {
return fmt.Errorf("unpair requires that the PIN be verified")
return errors.New("unpair requires that the PIN be verified")
}
return s.Channel.Unpair()
}
@@ -907,7 +907,7 @@ func (s *Session) initialize(seed []byte) error {
return err
}
if status == "Online" {
return fmt.Errorf("card is already initialized, cowardly refusing to proceed")
return errors.New("card is already initialized, cowardly refusing to proceed")
}
s.Wallet.lock.Lock()

View File

@@ -21,6 +21,7 @@ import (
)
func TestURLParsing(t *testing.T) {
t.Parallel()
url, err := parseURL("https://ethereum.org")
if err != nil {
t.Errorf("unexpected error: %v", err)
@@ -40,6 +41,7 @@ func TestURLParsing(t *testing.T) {
}
func TestURLString(t *testing.T) {
t.Parallel()
url := URL{Scheme: "https", Path: "ethereum.org"}
if url.String() != "https://ethereum.org" {
t.Errorf("expected: %v, got: %v", "https://ethereum.org", url.String())
@@ -52,10 +54,11 @@ func TestURLString(t *testing.T) {
}
func TestURLMarshalJSON(t *testing.T) {
t.Parallel()
url := URL{Scheme: "https", Path: "ethereum.org"}
json, err := url.MarshalJSON()
if err != nil {
t.Errorf("unexpcted error: %v", err)
t.Errorf("unexpected error: %v", err)
}
if string(json) != "\"https://ethereum.org\"" {
t.Errorf("expected: %v, got: %v", "\"https://ethereum.org\"", string(json))
@@ -63,10 +66,11 @@ func TestURLMarshalJSON(t *testing.T) {
}
func TestURLUnmarshalJSON(t *testing.T) {
t.Parallel()
url := &URL{}
err := url.UnmarshalJSON([]byte("\"https://ethereum.org\""))
if err != nil {
t.Errorf("unexpcted error: %v", err)
t.Errorf("unexpected error: %v", err)
}
if url.Scheme != "https" {
t.Errorf("expected: %v, got: %v", "https", url.Scheme)
@@ -77,6 +81,7 @@ func TestURLUnmarshalJSON(t *testing.T) {
}
func TestURLComparison(t *testing.T) {
t.Parallel()
tests := []struct {
urlA URL
urlB URL

View File

@@ -63,9 +63,9 @@ type Hub struct {
stateLock sync.RWMutex // Protects the internals of the hub from racey access
// TODO(karalabe): remove if hotplug lands on Windows
commsPend int // Number of operations blocking enumeration
commsLock sync.Mutex // Lock protecting the pending counter and enumeration
enumFails uint32 // Number of times enumeration has failed
commsPend int // Number of operations blocking enumeration
commsLock sync.Mutex // Lock protecting the pending counter and enumeration
enumFails atomic.Uint32 // Number of times enumeration has failed
}
// NewLedgerHub creates a new hardware wallet manager for Ledger devices.
@@ -151,7 +151,7 @@ func (hub *Hub) refreshWallets() {
return
}
// If USB enumeration is continually failing, don't keep trying indefinitely
if atomic.LoadUint32(&hub.enumFails) > 2 {
if hub.enumFails.Load() > 2 {
return
}
// Retrieve the current list of USB wallet devices
@@ -172,7 +172,7 @@ func (hub *Hub) refreshWallets() {
}
infos, err := usb.Enumerate(hub.vendorID, 0)
if err != nil {
failcount := atomic.AddUint32(&hub.enumFails, 1)
failcount := hub.enumFails.Add(1)
if runtime.GOOS == "linux" {
// See rationale before the enumeration why this is needed and only on Linux.
hub.commsLock.Unlock()
@@ -181,7 +181,7 @@ func (hub *Hub) refreshWallets() {
"vendor", hub.vendorID, "failcount", failcount, "err", err)
return
}
atomic.StoreUint32(&hub.enumFails, 0)
hub.enumFails.Store(0)
for _, info := range infos {
for _, id := range hub.productIDs {

View File

@@ -59,6 +59,8 @@ const (
ledgerP1InitTransactionData ledgerParam1 = 0x00 // First transaction data block for signing
ledgerP1ContTransactionData ledgerParam1 = 0x80 // Subsequent transaction data block for signing
ledgerP2DiscardAddressChainCode ledgerParam2 = 0x00 // Do not return the chain code along with the address
ledgerEip155Size int = 3 // Size of the EIP-155 chain_id,r,s in unsigned transactions
)
// errLedgerReplyInvalidHeader is the error message returned by a Ledger data exchange
@@ -347,9 +349,15 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
op = ledgerP1InitTransactionData
reply []byte
)
// Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
// https://github.com/LedgerHQ/app-ethereum/issues/409
chunk := 255
for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
}
for len(payload) > 0 {
// Calculate the size of the next data chunk
chunk := 255
if chunk > len(payload) {
chunk = len(payload)
}

View File

@@ -624,7 +624,7 @@ func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID
return signed, nil
}
// SignHashWithPassphrase implements accounts.Wallet, however signing arbitrary
// SignTextWithPassphrase implements accounts.Wallet, however signing arbitrary
// data is not supported for Ledger wallets, so this method will always return
// an error.
func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {

View File

@@ -26,7 +26,7 @@ for:
- go run build/ci.go lint
- go run build/ci.go install -dlgo
test_script:
- go run build/ci.go test -dlgo -coverage
- go run build/ci.go test -dlgo
# linux/386 is disabled.
- matrix:
@@ -54,4 +54,4 @@ for:
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
test_script:
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -coverage
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short

View File

@@ -74,13 +74,13 @@ var (
// - newPayloadV1: if the payload was accepted, but not processed (side chain)
ACCEPTED = "ACCEPTED"
INVALIDBLOCKHASH = "INVALID_BLOCK_HASH"
GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"}
UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"}
InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"}
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}

View File

@@ -20,12 +20,14 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
Random common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var enc PayloadAttributes
enc.Timestamp = hexutil.Uint64(p.Timestamp)
enc.Random = p.Random
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
enc.Withdrawals = p.Withdrawals
enc.BeaconRoot = p.BeaconRoot
return json.Marshal(&enc)
}
@@ -36,6 +38,7 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
Random *common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var dec PayloadAttributes
if err := json.Unmarshal(input, &dec); err != nil {
@@ -56,5 +59,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
if dec.Withdrawals != nil {
p.Withdrawals = dec.Withdrawals
}
if dec.BeaconRoot != nil {
p.BeaconRoot = dec.BeaconRoot
}
return nil
}

View File

@@ -32,6 +32,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
}
var enc ExecutableData
enc.ParentHash = e.ParentHash
@@ -54,6 +56,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
}
}
enc.Withdrawals = e.Withdrawals
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
return json.Marshal(&enc)
}
@@ -75,6 +79,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
}
var dec ExecutableData
if err := json.Unmarshal(input, &dec); err != nil {
@@ -142,5 +148,11 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
if dec.Withdrawals != nil {
e.Withdrawals = dec.Withdrawals
}
if dec.BlobGasUsed != nil {
e.BlobGasUsed = (*uint64)(dec.BlobGasUsed)
}
if dec.ExcessBlobGas != nil {
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
}
return nil
}

View File

@@ -17,10 +17,14 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
Override bool `json:"shouldOverrideBuilder"`
}
var enc ExecutionPayloadEnvelope
enc.ExecutionPayload = e.ExecutionPayload
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
enc.BlobsBundle = e.BlobsBundle
enc.Override = e.Override
return json.Marshal(&enc)
}
@@ -29,6 +33,8 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
Override *bool `json:"shouldOverrideBuilder"`
}
var dec ExecutionPayloadEnvelope
if err := json.Unmarshal(input, &dec); err != nil {
@@ -42,5 +48,11 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'blockValue' for ExecutionPayloadEnvelope")
}
e.BlockValue = (*big.Int)(dec.BlockValue)
if dec.BlobsBundle != nil {
e.BlobsBundle = dec.BlobsBundle
}
if dec.Override != nil {
e.Override = *dec.Override
}
return nil
}

View File

@@ -35,6 +35,7 @@ type PayloadAttributes struct {
Random common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
// JSON type overrides for PayloadAttributes.
@@ -61,6 +62,8 @@ type ExecutableData struct {
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
Transactions [][]byte `json:"transactions" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *uint64 `json:"blobGasUsed"`
ExcessBlobGas *uint64 `json:"excessBlobGas"`
}
// JSON type overrides for executableData.
@@ -73,6 +76,8 @@ type executableDataMarshaling struct {
ExtraData hexutil.Bytes
LogsBloom hexutil.Bytes
Transactions []hexutil.Bytes
BlobGasUsed *hexutil.Uint64
ExcessBlobGas *hexutil.Uint64
}
//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go
@@ -80,6 +85,14 @@ type executableDataMarshaling struct {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
Override bool `json:"shouldOverrideBuilder"`
}
type BlobsBundleV1 struct {
Commitments []hexutil.Bytes `json:"commitments"`
Proofs []hexutil.Bytes `json:"proofs"`
Blobs []hexutil.Bytes `json:"blobs"`
}
// JSON type overrides for ExecutionPayloadEnvelope.
@@ -152,14 +165,15 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
// ExecutableDataToBlock constructs a block from executable data.
// It verifies that the following fields:
//
// len(extraData) <= 32
// uncleHash = emptyUncleHash
// difficulty = 0
// len(extraData) <= 32
// uncleHash = emptyUncleHash
// difficulty = 0
// if versionedHashes != nil, versionedHashes match to blob transactions
//
// and that the blockhash of the constructed block matches the parameters. Nil
// Withdrawals value will propagate through the returned block. Empty
// Withdrawals value must be passed via non-nil, length 0 value in params.
func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) {
func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
txs, err := decodeTransactions(params.Transactions)
if err != nil {
return nil, err
@@ -174,6 +188,18 @@ func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) {
if params.BaseFeePerGas != nil && (params.BaseFeePerGas.Sign() == -1 || params.BaseFeePerGas.BitLen() > 256) {
return nil, fmt.Errorf("invalid baseFeePerGas: %v", params.BaseFeePerGas)
}
var blobHashes []common.Hash
for _, tx := range txs {
blobHashes = append(blobHashes, tx.BlobHashes()...)
}
if len(blobHashes) != len(versionedHashes) {
return nil, fmt.Errorf("invalid number of versionedHashes: %v blobHashes: %v", versionedHashes, blobHashes)
}
for i := 0; i < len(blobHashes); i++ {
if blobHashes[i] != versionedHashes[i] {
return nil, fmt.Errorf("invalid versionedHash at %v: %v blobHashes: %v", i, versionedHashes, blobHashes)
}
}
// Only set withdrawalsRoot if it is non-nil. This allows CLs to use
// ExecutableData before withdrawals are enabled by marshaling
// Withdrawals as the json null value.
@@ -183,22 +209,25 @@ func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) {
withdrawalsRoot = &h
}
header := &types.Header{
ParentHash: params.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: params.FeeRecipient,
Root: params.StateRoot,
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
ReceiptHash: params.ReceiptsRoot,
Bloom: types.BytesToBloom(params.LogsBloom),
Difficulty: common.Big0,
Number: new(big.Int).SetUint64(params.Number),
GasLimit: params.GasLimit,
GasUsed: params.GasUsed,
Time: params.Timestamp,
BaseFee: params.BaseFeePerGas,
Extra: params.ExtraData,
MixDigest: params.Random,
WithdrawalsHash: withdrawalsRoot,
ParentHash: params.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: params.FeeRecipient,
Root: params.StateRoot,
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
ReceiptHash: params.ReceiptsRoot,
Bloom: types.BytesToBloom(params.LogsBloom),
Difficulty: common.Big0,
Number: new(big.Int).SetUint64(params.Number),
GasLimit: params.GasLimit,
GasUsed: params.GasUsed,
Time: params.Timestamp,
BaseFee: params.BaseFeePerGas,
Extra: params.ExtraData,
MixDigest: params.Random,
WithdrawalsHash: withdrawalsRoot,
ExcessBlobGas: params.ExcessBlobGas,
BlobGasUsed: params.BlobGasUsed,
ParentBeaconRoot: beaconRoot,
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
if block.Hash() != params.BlockHash {
@@ -209,7 +238,7 @@ func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) {
// BlockToExecutableData constructs the ExecutableData structure by filling the
// fields from the given block. It assumes the given block is post-merge block.
func BlockToExecutableData(block *types.Block, fees *big.Int) *ExecutionPayloadEnvelope {
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope {
data := &ExecutableData{
BlockHash: block.Hash(),
ParentHash: block.ParentHash(),
@@ -226,12 +255,26 @@ func BlockToExecutableData(block *types.Block, fees *big.Int) *ExecutionPayloadE
Random: block.MixDigest(),
ExtraData: block.Extra(),
Withdrawals: block.Withdrawals(),
BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(),
}
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees}
bundle := BlobsBundleV1{
Commitments: make([]hexutil.Bytes, 0),
Blobs: make([]hexutil.Bytes, 0),
Proofs: make([]hexutil.Bytes, 0),
}
for _, sidecar := range sidecars {
for j := range sidecar.Blobs {
bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:]))
bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:]))
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
}
}
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
}
// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
type ExecutionPayloadBodyV1 struct {
TransactionData []hexutil.Bytes `json:"transactions"`
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
}

125
beacon/light/canonical.go Normal file
View File

@@ -0,0 +1,125 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package light
import (
"encoding/binary"
"fmt"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
)
// canonicalStore stores instances of the given type in a database and caches
// them in memory, associated with a continuous range of period numbers.
// Note: canonicalStore is not thread safe and it is the caller's responsibility
// to avoid concurrent access.
type canonicalStore[T any] struct {
keyPrefix []byte
periods periodRange
cache *lru.Cache[uint64, T]
}
// newCanonicalStore creates a new canonicalStore and loads all keys associated
// with the keyPrefix in order to determine the ranges available in the database.
func newCanonicalStore[T any](db ethdb.Iteratee, keyPrefix []byte) (*canonicalStore[T], error) {
cs := &canonicalStore[T]{
keyPrefix: keyPrefix,
cache: lru.NewCache[uint64, T](100),
}
var (
iter = db.NewIterator(keyPrefix, nil)
kl = len(keyPrefix)
first = true
)
defer iter.Release()
for iter.Next() {
if len(iter.Key()) != kl+8 {
log.Warn("Invalid key length in the canonical chain database", "key", fmt.Sprintf("%#x", iter.Key()))
continue
}
period := binary.BigEndian.Uint64(iter.Key()[kl : kl+8])
if first {
cs.periods.Start = period
} else if cs.periods.End != period {
return nil, fmt.Errorf("gap in the canonical chain database between periods %d and %d", cs.periods.End, period-1)
}
first = false
cs.periods.End = period + 1
}
return cs, nil
}
// databaseKey returns the database key belonging to the given period.
func (cs *canonicalStore[T]) databaseKey(period uint64) []byte {
return binary.BigEndian.AppendUint64(append([]byte{}, cs.keyPrefix...), period)
}
// add adds the given item to the database. It also ensures that the range remains
// continuous. Can be used either with a batch or database backend.
func (cs *canonicalStore[T]) add(backend ethdb.KeyValueWriter, period uint64, value T) error {
if !cs.periods.canExpand(period) {
return fmt.Errorf("period expansion is not allowed, first: %d, next: %d, period: %d", cs.periods.Start, cs.periods.End, period)
}
enc, err := rlp.EncodeToBytes(value)
if err != nil {
return err
}
if err := backend.Put(cs.databaseKey(period), enc); err != nil {
return err
}
cs.cache.Add(period, value)
cs.periods.expand(period)
return nil
}
// deleteFrom removes items starting from the given period.
func (cs *canonicalStore[T]) deleteFrom(db ethdb.KeyValueWriter, fromPeriod uint64) (deleted periodRange) {
keepRange, deleteRange := cs.periods.split(fromPeriod)
deleteRange.each(func(period uint64) {
db.Delete(cs.databaseKey(period))
cs.cache.Remove(period)
})
cs.periods = keepRange
return deleteRange
}
// get returns the item at the given period or the null value of the given type
// if no item is present.
func (cs *canonicalStore[T]) get(backend ethdb.KeyValueReader, period uint64) (T, bool) {
var null, value T
if !cs.periods.contains(period) {
return null, false
}
if value, ok := cs.cache.Get(period); ok {
return value, true
}
enc, err := backend.Get(cs.databaseKey(period))
if err != nil {
log.Error("Canonical store value not found", "period", period, "start", cs.periods.Start, "end", cs.periods.End)
return null, false
}
if err := rlp.DecodeBytes(enc, &value); err != nil {
log.Error("Error decoding canonical store value", "error", err)
return null, false
}
cs.cache.Add(period, value)
return value, true
}

View File

@@ -0,0 +1,514 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package light
import (
"errors"
"fmt"
"math"
"sync"
"time"
"github.com/ethereum/go-ethereum/beacon/params"
"github.com/ethereum/go-ethereum/beacon/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
)
var (
ErrNeedCommittee = errors.New("sync committee required")
ErrInvalidUpdate = errors.New("invalid committee update")
ErrInvalidPeriod = errors.New("invalid update period")
ErrWrongCommitteeRoot = errors.New("wrong committee root")
ErrCannotReorg = errors.New("can not reorg committee chain")
)
// CommitteeChain is a passive data structure that can validate, hold and update
// a chain of beacon light sync committees and updates. It requires at least one
// externally set fixed committee root at the beginning of the chain which can
// be set either based on a BootstrapData or a trusted source (a local beacon
// full node). This makes the structure useful for both light client and light
// server setups.
//
// It always maintains the following consistency constraints:
// - a committee can only be present if its root hash matches an existing fixed
// root or if it is proven by an update at the previous period
// - an update can only be present if a committee is present at the same period
// and the update signature is valid and has enough participants.
// The committee at the next period (proven by the update) should also be
// present (note that this means they can only be added together if neither
// is present yet). If a fixed root is present at the next period then the
// update can only be present if it proves the same committee root.
//
// Once synced to the current sync period, CommitteeChain can also validate
// signed beacon headers.
type CommitteeChain struct {
// chainmu guards against concurrent access to the canonicalStore structures
// (updates, committees, fixedCommitteeRoots) and ensures that they stay consistent
// with each other and with committeeCache.
chainmu sync.RWMutex
db ethdb.KeyValueStore
updates *canonicalStore[*types.LightClientUpdate]
committees *canonicalStore[*types.SerializedSyncCommittee]
fixedCommitteeRoots *canonicalStore[common.Hash]
committeeCache *lru.Cache[uint64, syncCommittee] // cache deserialized committees
clock mclock.Clock // monotonic clock (simulated clock in tests)
unixNano func() int64 // system clock (simulated clock in tests)
sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests)
config *types.ChainConfig
signerThreshold int
minimumUpdateScore types.UpdateScore
enforceTime bool // enforceTime specifies whether the age of a signed header should be checked
}
// NewCommitteeChain creates a new CommitteeChain.
func NewCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool) *CommitteeChain {
return newCommitteeChain(db, config, signerThreshold, enforceTime, blsVerifier{}, &mclock.System{}, func() int64 { return time.Now().UnixNano() })
}
// newCommitteeChain creates a new CommitteeChain with the option of replacing the
// clock source and signature verification for testing purposes.
func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain {
s := &CommitteeChain{
committeeCache: lru.NewCache[uint64, syncCommittee](10),
db: db,
sigVerifier: sigVerifier,
clock: clock,
unixNano: unixNano,
config: config,
signerThreshold: signerThreshold,
enforceTime: enforceTime,
minimumUpdateScore: types.UpdateScore{
SignerCount: uint32(signerThreshold),
SubPeriodIndex: params.SyncPeriodLength / 16,
},
}
var err1, err2, err3 error
if s.fixedCommitteeRoots, err1 = newCanonicalStore[common.Hash](db, rawdb.FixedCommitteeRootKey); err1 != nil {
log.Error("Error creating fixed committee root store", "error", err1)
}
if s.committees, err2 = newCanonicalStore[*types.SerializedSyncCommittee](db, rawdb.SyncCommitteeKey); err2 != nil {
log.Error("Error creating committee store", "error", err2)
}
if s.updates, err3 = newCanonicalStore[*types.LightClientUpdate](db, rawdb.BestUpdateKey); err3 != nil {
log.Error("Error creating update store", "error", err3)
}
if err1 != nil || err2 != nil || err3 != nil || !s.checkConstraints() {
log.Info("Resetting invalid committee chain")
s.Reset()
}
// roll back invalid updates (might be necessary if forks have been changed since last time)
for !s.updates.periods.isEmpty() {
update, ok := s.updates.get(s.db, s.updates.periods.End-1)
if !ok {
log.Error("Sync committee update missing", "period", s.updates.periods.End-1)
s.Reset()
break
}
if valid, err := s.verifyUpdate(update); err != nil {
log.Error("Error validating update", "period", s.updates.periods.End-1, "error", err)
} else if valid {
break
}
if err := s.rollback(s.updates.periods.End); err != nil {
log.Error("Error writing batch into chain database", "error", err)
}
}
if !s.committees.periods.isEmpty() {
log.Trace("Sync committee chain loaded", "first period", s.committees.periods.Start, "last period", s.committees.periods.End-1)
}
return s
}
// checkConstraints checks committee chain validity constraints
func (s *CommitteeChain) checkConstraints() bool {
isNotInFixedCommitteeRootRange := func(r periodRange) bool {
return s.fixedCommitteeRoots.periods.isEmpty() ||
r.Start < s.fixedCommitteeRoots.periods.Start ||
r.Start >= s.fixedCommitteeRoots.periods.End
}
valid := true
if !s.updates.periods.isEmpty() {
if isNotInFixedCommitteeRootRange(s.updates.periods) {
log.Error("Start update is not in the fixed roots range")
valid = false
}
if s.committees.periods.Start > s.updates.periods.Start || s.committees.periods.End <= s.updates.periods.End {
log.Error("Missing committees in update range")
valid = false
}
}
if !s.committees.periods.isEmpty() {
if isNotInFixedCommitteeRootRange(s.committees.periods) {
log.Error("Start committee is not in the fixed roots range")
valid = false
}
if s.committees.periods.End > s.fixedCommitteeRoots.periods.End && s.committees.periods.End > s.updates.periods.End+1 {
log.Error("Last committee is neither in the fixed roots range nor proven by updates")
valid = false
}
}
return valid
}
// Reset resets the committee chain.
func (s *CommitteeChain) Reset() {
s.chainmu.Lock()
defer s.chainmu.Unlock()
if err := s.rollback(0); err != nil {
log.Error("Error writing batch into chain database", "error", err)
}
}
// CheckpointInit initializes a CommitteeChain based on the checkpoint.
// Note: if the chain is already initialized and the committees proven by the
// checkpoint do match the existing chain then the chain is retained and the
// new checkpoint becomes fixed.
func (s *CommitteeChain) CheckpointInit(bootstrap *types.BootstrapData) error {
s.chainmu.Lock()
defer s.chainmu.Unlock()
if err := bootstrap.Validate(); err != nil {
return err
}
period := bootstrap.Header.SyncPeriod()
if err := s.deleteFixedCommitteeRootsFrom(period + 2); err != nil {
s.Reset()
return err
}
if s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot) != nil {
s.Reset()
if err := s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot); err != nil {
s.Reset()
return err
}
}
if err := s.addFixedCommitteeRoot(period+1, common.Hash(bootstrap.CommitteeBranch[0])); err != nil {
s.Reset()
return err
}
if err := s.addCommittee(period, bootstrap.Committee); err != nil {
s.Reset()
return err
}
return nil
}
// addFixedCommitteeRoot sets a fixed committee root at the given period.
// Note that the period where the first committee is added has to have a fixed
// root which can either come from a BootstrapData or a trusted source.
func (s *CommitteeChain) addFixedCommitteeRoot(period uint64, root common.Hash) error {
if root == (common.Hash{}) {
return ErrWrongCommitteeRoot
}
batch := s.db.NewBatch()
oldRoot := s.getCommitteeRoot(period)
if !s.fixedCommitteeRoots.periods.canExpand(period) {
// Note: the fixed committee root range should always be continuous and
// therefore the expected syncing method is to forward sync and optionally
// backward sync periods one by one, starting from a checkpoint. The only
// case when a root that is not adjacent to the already fixed ones can be
// fixed is when the same root has already been proven by an update chain.
// In this case the all roots in between can and should be fixed.
// This scenario makes sense when a new trusted checkpoint is added to an
// existing chain, ensuring that it will not be rolled back (might be
// important in case of low signer participation rate).
if root != oldRoot {
return ErrInvalidPeriod
}
// if the old root exists and matches the new one then it is guaranteed
// that the given period is after the existing fixed range and the roots
// in between can also be fixed.
for p := s.fixedCommitteeRoots.periods.End; p < period; p++ {
if err := s.fixedCommitteeRoots.add(batch, p, s.getCommitteeRoot(p)); err != nil {
return err
}
}
}
if oldRoot != (common.Hash{}) && (oldRoot != root) {
// existing old root was different, we have to reorg the chain
if err := s.rollback(period); err != nil {
return err
}
}
if err := s.fixedCommitteeRoots.add(batch, period, root); err != nil {
return err
}
if err := batch.Write(); err != nil {
log.Error("Error writing batch into chain database", "error", err)
return err
}
return nil
}
// deleteFixedCommitteeRootsFrom deletes fixed roots starting from the given period.
// It also maintains chain consistency, meaning that it also deletes updates and
// committees if they are no longer supported by a valid update chain.
func (s *CommitteeChain) deleteFixedCommitteeRootsFrom(period uint64) error {
if period >= s.fixedCommitteeRoots.periods.End {
return nil
}
batch := s.db.NewBatch()
s.fixedCommitteeRoots.deleteFrom(batch, period)
if s.updates.periods.isEmpty() || period <= s.updates.periods.Start {
// Note: the first period of the update chain should always be fixed so if
// the fixed root at the first update is removed then the entire update chain
// and the proven committees have to be removed. Earlier committees in the
// remaining fixed root range can stay.
s.updates.deleteFrom(batch, period)
s.deleteCommitteesFrom(batch, period)
} else {
// The update chain stays intact, some previously fixed committee roots might
// get unfixed but are still proven by the update chain. If there were
// committees present after the range proven by updates, those should be
// removed if the belonging fixed roots are also removed.
fromPeriod := s.updates.periods.End + 1 // not proven by updates
if period > fromPeriod {
fromPeriod = period // also not justified by fixed roots
}
s.deleteCommitteesFrom(batch, fromPeriod)
}
if err := batch.Write(); err != nil {
log.Error("Error writing batch into chain database", "error", err)
return err
}
return nil
}
// deleteCommitteesFrom deletes committees starting from the given period.
func (s *CommitteeChain) deleteCommitteesFrom(batch ethdb.Batch, period uint64) {
deleted := s.committees.deleteFrom(batch, period)
for period := deleted.Start; period < deleted.End; period++ {
s.committeeCache.Remove(period)
}
}
// addCommittee adds a committee at the given period if possible.
func (s *CommitteeChain) addCommittee(period uint64, committee *types.SerializedSyncCommittee) error {
if !s.committees.periods.canExpand(period) {
return ErrInvalidPeriod
}
root := s.getCommitteeRoot(period)
if root == (common.Hash{}) {
return ErrInvalidPeriod
}
if root != committee.Root() {
return ErrWrongCommitteeRoot
}
if !s.committees.periods.contains(period) {
if err := s.committees.add(s.db, period, committee); err != nil {
return err
}
s.committeeCache.Remove(period)
}
return nil
}
// InsertUpdate adds a new update if possible.
func (s *CommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommittee *types.SerializedSyncCommittee) error {
s.chainmu.Lock()
defer s.chainmu.Unlock()
period := update.AttestedHeader.Header.SyncPeriod()
if !s.updates.periods.canExpand(period) || !s.committees.periods.contains(period) {
return ErrInvalidPeriod
}
if s.minimumUpdateScore.BetterThan(update.Score()) {
return ErrInvalidUpdate
}
oldRoot := s.getCommitteeRoot(period + 1)
reorg := oldRoot != (common.Hash{}) && oldRoot != update.NextSyncCommitteeRoot
if oldUpdate, ok := s.updates.get(s.db, period); ok && !update.Score().BetterThan(oldUpdate.Score()) {
// a better or equal update already exists; no changes, only fail if new one tried to reorg
if reorg {
return ErrCannotReorg
}
return nil
}
if s.fixedCommitteeRoots.periods.contains(period+1) && reorg {
return ErrCannotReorg
}
if ok, err := s.verifyUpdate(update); err != nil {
return err
} else if !ok {
return ErrInvalidUpdate
}
addCommittee := !s.committees.periods.contains(period+1) || reorg
if addCommittee {
if nextCommittee == nil {
return ErrNeedCommittee
}
if nextCommittee.Root() != update.NextSyncCommitteeRoot {
return ErrWrongCommitteeRoot
}
}
if reorg {
if err := s.rollback(period + 1); err != nil {
return err
}
}
batch := s.db.NewBatch()
if addCommittee {
if err := s.committees.add(batch, period+1, nextCommittee); err != nil {
return err
}
s.committeeCache.Remove(period + 1)
}
if err := s.updates.add(batch, period, update); err != nil {
return err
}
if err := batch.Write(); err != nil {
log.Error("Error writing batch into chain database", "error", err)
return err
}
log.Info("Inserted new committee update", "period", period, "next committee root", update.NextSyncCommitteeRoot)
return nil
}
// NextSyncPeriod returns the next period where an update can be added and also
// whether the chain is initialized at all.
func (s *CommitteeChain) NextSyncPeriod() (uint64, bool) {
s.chainmu.RLock()
defer s.chainmu.RUnlock()
if s.committees.periods.isEmpty() {
return 0, false
}
if !s.updates.periods.isEmpty() {
return s.updates.periods.End, true
}
return s.committees.periods.End - 1, true
}
// rollback removes all committees and fixed roots from the given period and updates
// starting from the previous period.
func (s *CommitteeChain) rollback(period uint64) error {
max := s.updates.periods.End + 1
if s.committees.periods.End > max {
max = s.committees.periods.End
}
if s.fixedCommitteeRoots.periods.End > max {
max = s.fixedCommitteeRoots.periods.End
}
for max > period {
max--
batch := s.db.NewBatch()
s.deleteCommitteesFrom(batch, max)
s.fixedCommitteeRoots.deleteFrom(batch, max)
if max > 0 {
s.updates.deleteFrom(batch, max-1)
}
if err := batch.Write(); err != nil {
log.Error("Error writing batch into chain database", "error", err)
return err
}
}
return nil
}
// getCommitteeRoot returns the committee root at the given period, either fixed,
// proven by a previous update or both. It returns an empty hash if the committee
// root is unknown.
func (s *CommitteeChain) getCommitteeRoot(period uint64) common.Hash {
if root, ok := s.fixedCommitteeRoots.get(s.db, period); ok || period == 0 {
return root
}
if update, ok := s.updates.get(s.db, period-1); ok {
return update.NextSyncCommitteeRoot
}
return common.Hash{}
}
// getSyncCommittee returns the deserialized sync committee at the given period.
func (s *CommitteeChain) getSyncCommittee(period uint64) (syncCommittee, error) {
if c, ok := s.committeeCache.Get(period); ok {
return c, nil
}
if sc, ok := s.committees.get(s.db, period); ok {
c, err := s.sigVerifier.deserializeSyncCommittee(sc)
if err != nil {
return nil, fmt.Errorf("Sync committee #%d deserialization error: %v", period, err)
}
s.committeeCache.Add(period, c)
return c, nil
}
return nil, fmt.Errorf("Missing serialized sync committee #%d", period)
}
// VerifySignedHeader returns true if the given signed header has a valid signature
// according to the local committee chain. The caller should ensure that the
// committees advertised by the same source where the signed header came from are
// synced before verifying the signature.
// The age of the header is also returned (the time elapsed since the beginning
// of the given slot, according to the local system clock). If enforceTime is
// true then negative age (future) headers are rejected.
func (s *CommitteeChain) VerifySignedHeader(head types.SignedHeader) (bool, time.Duration, error) {
s.chainmu.RLock()
defer s.chainmu.RUnlock()
return s.verifySignedHeader(head)
}
func (s *CommitteeChain) verifySignedHeader(head types.SignedHeader) (bool, time.Duration, error) {
var age time.Duration
now := s.unixNano()
if head.Header.Slot < (uint64(now-math.MinInt64)/uint64(time.Second)-s.config.GenesisTime)/12 {
age = time.Duration(now - int64(time.Second)*int64(s.config.GenesisTime+head.Header.Slot*12))
} else {
age = time.Duration(math.MinInt64)
}
if s.enforceTime && age < 0 {
return false, age, nil
}
committee, err := s.getSyncCommittee(types.SyncPeriod(head.SignatureSlot))
if err != nil {
return false, 0, err
}
if committee == nil {
return false, age, nil
}
if signingRoot, err := s.config.Forks.SigningRoot(head.Header); err == nil {
return s.sigVerifier.verifySignature(committee, signingRoot, &head.Signature), age, nil
}
return false, age, nil
}
// verifyUpdate checks whether the header signature is correct and the update
// fits into the specified constraints (assumes that the update has been
// successfully validated previously)
func (s *CommitteeChain) verifyUpdate(update *types.LightClientUpdate) (bool, error) {
// Note: SignatureSlot determines the sync period of the committee used for signature
// verification. Though in reality SignatureSlot is always bigger than update.Header.Slot,
// setting them as equal here enforces the rule that they have to be in the same sync
// period in order for the light client update proof to be meaningful.
ok, age, err := s.verifySignedHeader(update.AttestedHeader)
if age < 0 {
log.Warn("Future committee update received", "age", age)
}
return ok, err
}

View File

@@ -0,0 +1,356 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package light
import (
"crypto/rand"
"testing"
"time"
"github.com/ethereum/go-ethereum/beacon/params"
"github.com/ethereum/go-ethereum/beacon/types"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
)
var (
testGenesis = newTestGenesis()
testGenesis2 = newTestGenesis()
tfBase = newTestForks(testGenesis, types.Forks{
&types.Fork{Epoch: 0, Version: []byte{0}},
})
tfAlternative = newTestForks(testGenesis, types.Forks{
&types.Fork{Epoch: 0, Version: []byte{0}},
&types.Fork{Epoch: 0x700, Version: []byte{1}},
})
tfAnotherGenesis = newTestForks(testGenesis2, types.Forks{
&types.Fork{Epoch: 0, Version: []byte{0}},
})
tcBase = newTestCommitteeChain(nil, tfBase, true, 0, 10, 400, false)
tcBaseWithInvalidUpdates = newTestCommitteeChain(tcBase, tfBase, false, 5, 10, 200, false) // signer count too low
tcBaseWithBetterUpdates = newTestCommitteeChain(tcBase, tfBase, false, 5, 10, 440, false)
tcReorgWithWorseUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 400, false)
tcReorgWithWorseUpdates2 = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 380, false)
tcReorgWithBetterUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 420, false)
tcReorgWithFinalizedUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 400, true)
tcFork = newTestCommitteeChain(tcBase, tfAlternative, true, 7, 10, 400, false)
tcAnotherGenesis = newTestCommitteeChain(nil, tfAnotherGenesis, true, 0, 10, 400, false)
)
func TestCommitteeChainFixedCommitteeRoots(t *testing.T) {
for _, reload := range []bool{false, true} {
c := newCommitteeChainTest(t, tfBase, 300, true)
c.setClockPeriod(7)
c.addFixedCommitteeRoot(tcBase, 4, nil)
c.addFixedCommitteeRoot(tcBase, 5, nil)
c.addFixedCommitteeRoot(tcBase, 6, nil)
c.addFixedCommitteeRoot(tcBase, 8, ErrInvalidPeriod) // range has to be continuous
c.addFixedCommitteeRoot(tcBase, 3, nil)
c.addFixedCommitteeRoot(tcBase, 2, nil)
if reload {
c.reloadChain()
}
c.addCommittee(tcBase, 4, nil)
c.addCommittee(tcBase, 6, ErrInvalidPeriod) // range has to be continuous
c.addCommittee(tcBase, 5, nil)
c.addCommittee(tcBase, 6, nil)
c.addCommittee(tcAnotherGenesis, 3, ErrWrongCommitteeRoot)
c.addCommittee(tcBase, 3, nil)
if reload {
c.reloadChain()
}
c.verifyRange(tcBase, 3, 6)
}
}
func TestCommitteeChainCheckpointSync(t *testing.T) {
for _, enforceTime := range []bool{false, true} {
for _, reload := range []bool{false, true} {
c := newCommitteeChainTest(t, tfBase, 300, enforceTime)
if enforceTime {
c.setClockPeriod(6)
}
c.insertUpdate(tcBase, 3, true, ErrInvalidPeriod)
c.addFixedCommitteeRoot(tcBase, 3, nil)
c.addFixedCommitteeRoot(tcBase, 4, nil)
c.insertUpdate(tcBase, 4, true, ErrInvalidPeriod) // still no committee
c.addCommittee(tcBase, 3, nil)
c.addCommittee(tcBase, 4, nil)
if reload {
c.reloadChain()
}
c.verifyRange(tcBase, 3, 4)
c.insertUpdate(tcBase, 3, false, nil) // update can be added without committee here
c.insertUpdate(tcBase, 4, false, ErrNeedCommittee) // but not here as committee 5 is not there yet
c.insertUpdate(tcBase, 4, true, nil)
c.verifyRange(tcBase, 3, 5)
c.insertUpdate(tcBaseWithInvalidUpdates, 5, true, ErrInvalidUpdate) // signer count too low
c.insertUpdate(tcBase, 5, true, nil)
if reload {
c.reloadChain()
}
if enforceTime {
c.insertUpdate(tcBase, 6, true, ErrInvalidUpdate) // future update rejected
c.setClockPeriod(7)
}
c.insertUpdate(tcBase, 6, true, nil) // when the time comes it's accepted
if reload {
c.reloadChain()
}
if enforceTime {
c.verifyRange(tcBase, 3, 6) // committee 7 is there but still in the future
c.setClockPeriod(8)
}
c.verifyRange(tcBase, 3, 7) // now period 7 can also be verified
// try reverse syncing an update
c.insertUpdate(tcBase, 2, false, ErrInvalidPeriod) // fixed committee is needed first
c.addFixedCommitteeRoot(tcBase, 2, nil)
c.addCommittee(tcBase, 2, nil)
c.insertUpdate(tcBase, 2, false, nil)
c.verifyRange(tcBase, 2, 7)
}
}
}
func TestCommitteeChainReorg(t *testing.T) {
for _, reload := range []bool{false, true} {
for _, addBetterUpdates := range []bool{false, true} {
c := newCommitteeChainTest(t, tfBase, 300, true)
c.setClockPeriod(11)
c.addFixedCommitteeRoot(tcBase, 3, nil)
c.addFixedCommitteeRoot(tcBase, 4, nil)
c.addCommittee(tcBase, 3, nil)
for period := uint64(3); period < 10; period++ {
c.insertUpdate(tcBase, period, true, nil)
}
if reload {
c.reloadChain()
}
c.verifyRange(tcBase, 3, 10)
c.insertUpdate(tcReorgWithWorseUpdates, 5, true, ErrCannotReorg)
c.insertUpdate(tcReorgWithWorseUpdates2, 5, true, ErrCannotReorg)
if addBetterUpdates {
// add better updates for the base chain and expect first reorg to fail
// (only add updates as committees should be the same)
for period := uint64(5); period < 10; period++ {
c.insertUpdate(tcBaseWithBetterUpdates, period, false, nil)
}
if reload {
c.reloadChain()
}
c.verifyRange(tcBase, 3, 10) // still on the same chain
c.insertUpdate(tcReorgWithBetterUpdates, 5, true, ErrCannotReorg)
} else {
// reorg with better updates
c.insertUpdate(tcReorgWithBetterUpdates, 5, false, ErrNeedCommittee)
c.verifyRange(tcBase, 3, 10) // no success yet, still on the base chain
c.verifyRange(tcReorgWithBetterUpdates, 3, 5)
c.insertUpdate(tcReorgWithBetterUpdates, 5, true, nil)
// successful reorg, base chain should only match before the reorg period
if reload {
c.reloadChain()
}
c.verifyRange(tcBase, 3, 5)
c.verifyRange(tcReorgWithBetterUpdates, 3, 6)
for period := uint64(6); period < 10; period++ {
c.insertUpdate(tcReorgWithBetterUpdates, period, true, nil)
}
c.verifyRange(tcReorgWithBetterUpdates, 3, 10)
}
// reorg with finalized updates; should succeed even if base chain updates
// have been improved because a finalized update beats everything else
c.insertUpdate(tcReorgWithFinalizedUpdates, 5, false, ErrNeedCommittee)
c.insertUpdate(tcReorgWithFinalizedUpdates, 5, true, nil)
if reload {
c.reloadChain()
}
c.verifyRange(tcReorgWithFinalizedUpdates, 3, 6)
for period := uint64(6); period < 10; period++ {
c.insertUpdate(tcReorgWithFinalizedUpdates, period, true, nil)
}
c.verifyRange(tcReorgWithFinalizedUpdates, 3, 10)
}
}
}
func TestCommitteeChainFork(t *testing.T) {
c := newCommitteeChainTest(t, tfAlternative, 300, true)
c.setClockPeriod(11)
// trying to sync a chain on an alternative fork with the base chain data
c.addFixedCommitteeRoot(tcBase, 0, nil)
c.addFixedCommitteeRoot(tcBase, 1, nil)
c.addCommittee(tcBase, 0, nil)
// shared section should sync without errors
for period := uint64(0); period < 7; period++ {
c.insertUpdate(tcBase, period, true, nil)
}
c.insertUpdate(tcBase, 7, true, ErrInvalidUpdate) // wrong fork
// committee root #7 is still the same but signatures are already signed with
// a different fork id so period 7 should only verify on the alternative fork
c.verifyRange(tcBase, 0, 6)
c.verifyRange(tcFork, 0, 7)
for period := uint64(7); period < 10; period++ {
c.insertUpdate(tcFork, period, true, nil)
}
c.verifyRange(tcFork, 0, 10)
// reload the chain while switching to the base fork
c.config = tfBase
c.reloadChain()
// updates 7..9 should be rolled back now
c.verifyRange(tcFork, 0, 6) // again, period 7 only verifies on the right fork
c.verifyRange(tcBase, 0, 7)
c.insertUpdate(tcFork, 7, true, ErrInvalidUpdate) // wrong fork
for period := uint64(7); period < 10; period++ {
c.insertUpdate(tcBase, period, true, nil)
}
c.verifyRange(tcBase, 0, 10)
}
type committeeChainTest struct {
t *testing.T
db *memorydb.Database
clock *mclock.Simulated
config types.ChainConfig
signerThreshold int
enforceTime bool
chain *CommitteeChain
}
func newCommitteeChainTest(t *testing.T, config types.ChainConfig, signerThreshold int, enforceTime bool) *committeeChainTest {
c := &committeeChainTest{
t: t,
db: memorydb.New(),
clock: &mclock.Simulated{},
config: config,
signerThreshold: signerThreshold,
enforceTime: enforceTime,
}
c.chain = newCommitteeChain(c.db, &config, signerThreshold, enforceTime, dummyVerifier{}, c.clock, func() int64 { return int64(c.clock.Now()) })
return c
}
func (c *committeeChainTest) reloadChain() {
c.chain = newCommitteeChain(c.db, &c.config, c.signerThreshold, c.enforceTime, dummyVerifier{}, c.clock, func() int64 { return int64(c.clock.Now()) })
}
func (c *committeeChainTest) setClockPeriod(period float64) {
target := mclock.AbsTime(period * float64(time.Second*12*params.SyncPeriodLength))
wait := time.Duration(target - c.clock.Now())
if wait < 0 {
c.t.Fatalf("Invalid setClockPeriod")
}
c.clock.Run(wait)
}
func (c *committeeChainTest) addFixedCommitteeRoot(tc *testCommitteeChain, period uint64, expErr error) {
if err := c.chain.addFixedCommitteeRoot(period, tc.periods[period].committee.Root()); err != expErr {
c.t.Errorf("Incorrect error output from addFixedCommitteeRoot at period %d (expected %v, got %v)", period, expErr, err)
}
}
func (c *committeeChainTest) addCommittee(tc *testCommitteeChain, period uint64, expErr error) {
if err := c.chain.addCommittee(period, tc.periods[period].committee); err != expErr {
c.t.Errorf("Incorrect error output from addCommittee at period %d (expected %v, got %v)", period, expErr, err)
}
}
func (c *committeeChainTest) insertUpdate(tc *testCommitteeChain, period uint64, addCommittee bool, expErr error) {
var committee *types.SerializedSyncCommittee
if addCommittee {
committee = tc.periods[period+1].committee
}
if err := c.chain.InsertUpdate(tc.periods[period].update, committee); err != expErr {
c.t.Errorf("Incorrect error output from InsertUpdate at period %d (expected %v, got %v)", period, expErr, err)
}
}
func (c *committeeChainTest) verifySignedHeader(tc *testCommitteeChain, period float64, expOk bool) {
slot := uint64(period * float64(params.SyncPeriodLength))
signedHead := GenerateTestSignedHeader(types.Header{Slot: slot}, &tc.config, tc.periods[types.SyncPeriod(slot)].committee, slot+1, 400)
if ok, _, _ := c.chain.VerifySignedHeader(signedHead); ok != expOk {
c.t.Errorf("Incorrect output from VerifySignedHeader at period %f (expected %v, got %v)", period, expOk, ok)
}
}
func (c *committeeChainTest) verifyRange(tc *testCommitteeChain, begin, end uint64) {
if begin > 0 {
c.verifySignedHeader(tc, float64(begin)-0.5, false)
}
for period := begin; period <= end; period++ {
c.verifySignedHeader(tc, float64(period)+0.5, true)
}
c.verifySignedHeader(tc, float64(end)+1.5, false)
}
func newTestGenesis() types.ChainConfig {
var config types.ChainConfig
rand.Read(config.GenesisValidatorsRoot[:])
return config
}
func newTestForks(config types.ChainConfig, forks types.Forks) types.ChainConfig {
for _, fork := range forks {
config.AddFork(fork.Name, fork.Epoch, fork.Version)
}
return config
}
func newTestCommitteeChain(parent *testCommitteeChain, config types.ChainConfig, newCommittees bool, begin, end int, signerCount int, finalizedHeader bool) *testCommitteeChain {
tc := &testCommitteeChain{
config: config,
}
if parent != nil {
tc.periods = make([]testPeriod, len(parent.periods))
copy(tc.periods, parent.periods)
}
if newCommittees {
if begin == 0 {
tc.fillCommittees(begin, end+1)
} else {
tc.fillCommittees(begin+1, end+1)
}
}
tc.fillUpdates(begin, end, signerCount, finalizedHeader)
return tc
}
type testPeriod struct {
committee *types.SerializedSyncCommittee
update *types.LightClientUpdate
}
type testCommitteeChain struct {
periods []testPeriod
config types.ChainConfig
}
func (tc *testCommitteeChain) fillCommittees(begin, end int) {
if len(tc.periods) <= end {
tc.periods = append(tc.periods, make([]testPeriod, end+1-len(tc.periods))...)
}
for i := begin; i <= end; i++ {
tc.periods[i].committee = GenerateTestCommittee()
}
}
func (tc *testCommitteeChain) fillUpdates(begin, end int, signerCount int, finalizedHeader bool) {
for i := begin; i <= end; i++ {
tc.periods[i].update = GenerateTestUpdate(&tc.config, uint64(i), tc.periods[i].committee, tc.periods[i+1].committee, signerCount, finalizedHeader)
}
}

78
beacon/light/range.go Normal file
View File

@@ -0,0 +1,78 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package light
// periodRange represents a (possibly zero-length) range of integers (sync periods).
type periodRange struct {
Start, End uint64
}
// isEmpty returns true if the length of the range is zero.
func (a periodRange) isEmpty() bool {
return a.End == a.Start
}
// contains returns true if the range includes the given period.
func (a periodRange) contains(period uint64) bool {
return period >= a.Start && period < a.End
}
// canExpand returns true if the range includes or can be expanded with the given
// period (either the range is empty or the given period is inside, right before or
// right after the range).
func (a periodRange) canExpand(period uint64) bool {
return a.isEmpty() || (period+1 >= a.Start && period <= a.End)
}
// expand expands the range with the given period.
// This method assumes that canExpand returned true: otherwise this is a no-op.
func (a *periodRange) expand(period uint64) {
if a.isEmpty() {
a.Start, a.End = period, period+1
return
}
if a.Start == period+1 {
a.Start--
}
if a.End == period {
a.End++
}
}
// split splits the range into two ranges. The 'fromPeriod' will be the first
// element in the second range (if present).
// The original range is unchanged by this operation
func (a *periodRange) split(fromPeriod uint64) (periodRange, periodRange) {
if fromPeriod <= a.Start {
// First range empty, everything in second range,
return periodRange{}, *a
}
if fromPeriod >= a.End {
// Second range empty, everything in first range,
return *a, periodRange{}
}
x := periodRange{a.Start, fromPeriod}
y := periodRange{fromPeriod, a.End}
return x, y
}
// each invokes the supplied function fn once per period in range
func (a *periodRange) each(fn func(uint64)) {
for p := a.Start; p < a.End; p++ {
fn(p)
}
}

View File

@@ -0,0 +1,152 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package light
import (
"crypto/rand"
"crypto/sha256"
mrand "math/rand"
"github.com/ethereum/go-ethereum/beacon/merkle"
"github.com/ethereum/go-ethereum/beacon/params"
"github.com/ethereum/go-ethereum/beacon/types"
"github.com/ethereum/go-ethereum/common"
)
func GenerateTestCommittee() *types.SerializedSyncCommittee {
s := new(types.SerializedSyncCommittee)
rand.Read(s[:32])
return s
}
func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nextCommittee *types.SerializedSyncCommittee, signerCount int, finalizedHeader bool) *types.LightClientUpdate {
update := new(types.LightClientUpdate)
update.NextSyncCommitteeRoot = nextCommittee.Root()
var attestedHeader types.Header
if finalizedHeader {
update.FinalizedHeader = new(types.Header)
*update.FinalizedHeader, update.NextSyncCommitteeBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+100, params.StateIndexNextSyncCommittee, merkle.Value(update.NextSyncCommitteeRoot))
attestedHeader, update.FinalityBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+200, params.StateIndexFinalBlock, merkle.Value(update.FinalizedHeader.Hash()))
} else {
attestedHeader, update.NextSyncCommitteeBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+2000, params.StateIndexNextSyncCommittee, merkle.Value(update.NextSyncCommitteeRoot))
}
update.AttestedHeader = GenerateTestSignedHeader(attestedHeader, config, committee, attestedHeader.Slot+1, signerCount)
return update
}
func GenerateTestSignedHeader(header types.Header, config *types.ChainConfig, committee *types.SerializedSyncCommittee, signatureSlot uint64, signerCount int) types.SignedHeader {
bitmask := makeBitmask(signerCount)
signingRoot, _ := config.Forks.SigningRoot(header)
c, _ := dummyVerifier{}.deserializeSyncCommittee(committee)
return types.SignedHeader{
Header: header,
Signature: types.SyncAggregate{
Signers: bitmask,
Signature: makeDummySignature(c.(dummySyncCommittee), signingRoot, bitmask),
},
SignatureSlot: signatureSlot,
}
}
func GenerateTestCheckpoint(period uint64, committee *types.SerializedSyncCommittee) *types.BootstrapData {
header, branch := makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+200, params.StateIndexSyncCommittee, merkle.Value(committee.Root()))
return &types.BootstrapData{
Header: header,
Committee: committee,
CommitteeRoot: committee.Root(),
CommitteeBranch: branch,
}
}
func makeBitmask(signerCount int) (bitmask [params.SyncCommitteeBitmaskSize]byte) {
for i := 0; i < params.SyncCommitteeSize; i++ {
if mrand.Intn(params.SyncCommitteeSize-i) < signerCount {
bitmask[i/8] += byte(1) << (i & 7)
signerCount--
}
}
return
}
func makeTestHeaderWithMerkleProof(slot, index uint64, value merkle.Value) (types.Header, merkle.Values) {
var branch merkle.Values
hasher := sha256.New()
for index > 1 {
var proofHash merkle.Value
rand.Read(proofHash[:])
hasher.Reset()
if index&1 == 0 {
hasher.Write(value[:])
hasher.Write(proofHash[:])
} else {
hasher.Write(proofHash[:])
hasher.Write(value[:])
}
hasher.Sum(value[:0])
index >>= 1
branch = append(branch, proofHash)
}
return types.Header{Slot: slot, StateRoot: common.Hash(value)}, branch
}
// syncCommittee holds either a blsSyncCommittee or a fake dummySyncCommittee used for testing
type syncCommittee interface{}
// committeeSigVerifier verifies sync committee signatures (either proper BLS
// signatures or fake signatures used for testing)
type committeeSigVerifier interface {
deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error)
verifySignature(committee syncCommittee, signedRoot common.Hash, aggregate *types.SyncAggregate) bool
}
// blsVerifier implements committeeSigVerifier
type blsVerifier struct{}
// deserializeSyncCommittee implements committeeSigVerifier
func (blsVerifier) deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error) {
return s.Deserialize()
}
// verifySignature implements committeeSigVerifier
func (blsVerifier) verifySignature(committee syncCommittee, signingRoot common.Hash, aggregate *types.SyncAggregate) bool {
return committee.(*types.SyncCommittee).VerifySignature(signingRoot, aggregate)
}
type dummySyncCommittee [32]byte
// dummyVerifier implements committeeSigVerifier
type dummyVerifier struct{}
// deserializeSyncCommittee implements committeeSigVerifier
func (dummyVerifier) deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error) {
var sc dummySyncCommittee
copy(sc[:], s[:32])
return sc, nil
}
// verifySignature implements committeeSigVerifier
func (dummyVerifier) verifySignature(committee syncCommittee, signingRoot common.Hash, aggregate *types.SyncAggregate) bool {
return aggregate.Signature == makeDummySignature(committee.(dummySyncCommittee), signingRoot, aggregate.Signers)
}
func makeDummySignature(committee dummySyncCommittee, signingRoot common.Hash, bitmask [params.SyncCommitteeBitmaskSize]byte) (sig [params.BLSSignatureSize]byte) {
for i, b := range committee[:] {
sig[i] = b ^ signingRoot[i]
}
copy(sig[32:], bitmask[:])
return
}

67
beacon/merkle/merkle.go Normal file
View File

@@ -0,0 +1,67 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package merkle implements proof verifications in binary merkle trees.
package merkle
import (
"crypto/sha256"
"errors"
"reflect"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
// Value represents either a 32 byte leaf value or hash node in a binary merkle tree/partial proof.
type Value [32]byte
// Values represent a series of merkle tree leaves/nodes.
type Values []Value
var valueT = reflect.TypeOf(Value{})
// UnmarshalJSON parses a merkle value in hex syntax.
func (m *Value) UnmarshalJSON(input []byte) error {
return hexutil.UnmarshalFixedJSON(valueT, input, m[:])
}
// VerifyProof verifies a Merkle proof branch for a single value in a
// binary Merkle tree (index is a generalized tree index).
func VerifyProof(root common.Hash, index uint64, branch Values, value Value) error {
hasher := sha256.New()
for _, sibling := range branch {
hasher.Reset()
if index&1 == 0 {
hasher.Write(value[:])
hasher.Write(sibling[:])
} else {
hasher.Write(sibling[:])
hasher.Write(value[:])
}
hasher.Sum(value[:0])
if index >>= 1; index == 0 {
return errors.New("branch has extra items")
}
}
if index != 1 {
return errors.New("branch is missing items")
}
if common.Hash(value) != root {
return errors.New("root mismatch")
}
return nil
}

View File

@@ -1,4 +1,4 @@
// Copyright 2021 The go-ethereum Authors
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -14,22 +14,31 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//go:build linux
// +build linux
package params
package ethash
const (
EpochLength = 32
SyncPeriodLength = 8192
import (
"os"
BLSSignatureSize = 96
BLSPubkeySize = 48
"golang.org/x/sys/unix"
SyncCommitteeSize = 512
SyncCommitteeBitmaskSize = SyncCommitteeSize / 8
SyncCommitteeSupermajority = (SyncCommitteeSize*2 + 2) / 3
)
// ensureSize expands the file to the given size. This is to prevent runtime
// errors later on, if the underlying file expands beyond the disk capacity,
// even though it ostensibly is already expanded, but due to being sparse
// does not actually occupy the full declared size on disk.
func ensureSize(f *os.File, size int64) error {
// Docs: https://www.man7.org/linux/man-pages/man2/fallocate.2.html
return unix.Fallocate(int(f.Fd()), 0, 0, size)
}
const (
StateIndexGenesisTime = 32
StateIndexGenesisValidators = 33
StateIndexForkVersion = 141
StateIndexLatestHeader = 36
StateIndexBlockRoots = 37
StateIndexStateRoots = 38
StateIndexHistoricRoots = 39
StateIndexFinalBlock = 105
StateIndexSyncCommittee = 54
StateIndexNextSyncCommittee = 55
StateIndexExecPayload = 56
StateIndexExecHead = 908
)

191
beacon/types/committee.go Normal file
View File

@@ -0,0 +1,191 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package types
import (
"crypto/sha256"
"encoding/json"
"fmt"
"math/bits"
"github.com/ethereum/go-ethereum/beacon/params"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
bls "github.com/protolambda/bls12-381-util"
)
// SerializedSyncCommitteeSize is the size of the sync committee plus the
// aggregate public key.
const SerializedSyncCommitteeSize = (params.SyncCommitteeSize + 1) * params.BLSPubkeySize
// SerializedSyncCommittee is the serialized version of a sync committee
// plus the aggregate public key.
type SerializedSyncCommittee [SerializedSyncCommitteeSize]byte
// jsonSyncCommittee is the JSON representation of a sync committee.
//
// See data structure definition here:
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate
type jsonSyncCommittee struct {
Pubkeys []hexutil.Bytes `json:"pubkeys"`
Aggregate hexutil.Bytes `json:"aggregate_pubkey"`
}
// MarshalJSON implements json.Marshaler.
func (s *SerializedSyncCommittee) MarshalJSON() ([]byte, error) {
sc := jsonSyncCommittee{Pubkeys: make([]hexutil.Bytes, params.SyncCommitteeSize)}
for i := range sc.Pubkeys {
sc.Pubkeys[i] = make(hexutil.Bytes, params.BLSPubkeySize)
copy(sc.Pubkeys[i][:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize])
}
sc.Aggregate = make(hexutil.Bytes, params.BLSPubkeySize)
copy(sc.Aggregate[:], s[params.SyncCommitteeSize*params.BLSPubkeySize:])
return json.Marshal(&sc)
}
// UnmarshalJSON implements json.Marshaler.
func (s *SerializedSyncCommittee) UnmarshalJSON(input []byte) error {
var sc jsonSyncCommittee
if err := json.Unmarshal(input, &sc); err != nil {
return err
}
if len(sc.Pubkeys) != params.SyncCommitteeSize {
return fmt.Errorf("invalid number of pubkeys %d", len(sc.Pubkeys))
}
for i, key := range sc.Pubkeys {
if len(key) != params.BLSPubkeySize {
return fmt.Errorf("pubkey %d has invalid size %d", i, len(key))
}
copy(s[i*params.BLSPubkeySize:], key[:])
}
if len(sc.Aggregate) != params.BLSPubkeySize {
return fmt.Errorf("invalid aggregate pubkey size %d", len(sc.Aggregate))
}
copy(s[params.SyncCommitteeSize*params.BLSPubkeySize:], sc.Aggregate[:])
return nil
}
// Root calculates the root hash of the binary tree representation of a sync
// committee provided in serialized format.
//
// TODO(zsfelfoldi): Get rid of this when SSZ encoding lands.
func (s *SerializedSyncCommittee) Root() common.Hash {
var (
hasher = sha256.New()
padding [64 - params.BLSPubkeySize]byte
data [params.SyncCommitteeSize]common.Hash
l = params.SyncCommitteeSize
)
for i := range data {
hasher.Reset()
hasher.Write(s[i*params.BLSPubkeySize : (i+1)*params.BLSPubkeySize])
hasher.Write(padding[:])
hasher.Sum(data[i][:0])
}
for l > 1 {
for i := 0; i < l/2; i++ {
hasher.Reset()
hasher.Write(data[i*2][:])
hasher.Write(data[i*2+1][:])
hasher.Sum(data[i][:0])
}
l /= 2
}
hasher.Reset()
hasher.Write(s[SerializedSyncCommitteeSize-params.BLSPubkeySize : SerializedSyncCommitteeSize])
hasher.Write(padding[:])
hasher.Sum(data[1][:0])
hasher.Reset()
hasher.Write(data[0][:])
hasher.Write(data[1][:])
hasher.Sum(data[0][:0])
return data[0]
}
// Deserialize splits open the pubkeys into proper BLS key types.
func (s *SerializedSyncCommittee) Deserialize() (*SyncCommittee, error) {
sc := new(SyncCommittee)
for i := 0; i <= params.SyncCommitteeSize; i++ {
key := new(bls.Pubkey)
var bytes [params.BLSPubkeySize]byte
copy(bytes[:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize])
if err := key.Deserialize(&bytes); err != nil {
return nil, err
}
if i < params.SyncCommitteeSize {
sc.keys[i] = key
} else {
sc.aggregate = key
}
}
return sc, nil
}
// SyncCommittee is a set of sync committee signer pubkeys and the aggregate key.
//
// See data structure definition here:
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate
type SyncCommittee struct {
keys [params.SyncCommitteeSize]*bls.Pubkey
aggregate *bls.Pubkey
}
// VerifySignature returns true if the given sync aggregate is a valid signature
// or the given hash.
func (sc *SyncCommittee) VerifySignature(signingRoot common.Hash, signature *SyncAggregate) bool {
var (
sig bls.Signature
keys = make([]*bls.Pubkey, 0, params.SyncCommitteeSize)
)
if err := sig.Deserialize(&signature.Signature); err != nil {
return false
}
for i, key := range sc.keys {
if signature.Signers[i/8]&(byte(1)<<(i%8)) != 0 {
keys = append(keys, key)
}
}
return bls.FastAggregateVerify(keys, signingRoot[:], &sig)
}
//go:generate go run github.com/fjl/gencodec -type SyncAggregate -field-override syncAggregateMarshaling -out gen_syncaggregate_json.go
// SyncAggregate represents an aggregated BLS signature with Signers referring
// to a subset of the corresponding sync committee.
//
// See data structure definition here:
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate
type SyncAggregate struct {
Signers [params.SyncCommitteeBitmaskSize]byte `gencodec:"required" json:"sync_committee_bits"`
Signature [params.BLSSignatureSize]byte `gencodec:"required" json:"sync_committee_signature"`
}
type syncAggregateMarshaling struct {
Signers hexutil.Bytes
Signature hexutil.Bytes
}
// SignerCount returns the number of signers in the aggregate signature.
func (s *SyncAggregate) SignerCount() int {
var count int
for _, v := range s.Signers {
count += bits.OnesCount8(v)
}
return count
}

176
beacon/types/config.go Normal file
View File

@@ -0,0 +1,176 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package types
import (
"crypto/sha256"
"fmt"
"os"
"sort"
"strconv"
"strings"
"github.com/ethereum/go-ethereum/beacon/merkle"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"gopkg.in/yaml.v3"
)
// syncCommitteeDomain specifies the signatures specific use to avoid clashes
// across signing different data structures.
const syncCommitteeDomain = 7
// Fork describes a single beacon chain fork and also stores the calculated
// signature domain used after this fork.
type Fork struct {
// Name of the fork in the chain config (config.yaml) file{
Name string
// Epoch when given fork version is activated
Epoch uint64
// Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types
Version []byte
// calculated by computeDomain, based on fork version and genesis validators root
domain merkle.Value
}
// computeDomain returns the signature domain based on the given fork version
// and genesis validator set root.
func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) {
var (
hasher = sha256.New()
forkVersion32 merkle.Value
forkDataRoot merkle.Value
)
copy(forkVersion32[:], f.Version)
hasher.Write(forkVersion32[:])
hasher.Write(genesisValidatorsRoot[:])
hasher.Sum(forkDataRoot[:0])
f.domain[0] = syncCommitteeDomain
copy(f.domain[4:], forkDataRoot[:28])
}
// Forks is the list of all beacon chain forks in the chain configuration.
type Forks []*Fork
// domain returns the signature domain for the given epoch (assumes that domains
// have already been calculated).
func (f Forks) domain(epoch uint64) (merkle.Value, error) {
for i := len(f) - 1; i >= 0; i-- {
if epoch >= f[i].Epoch {
return f[i].domain, nil
}
}
return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch)
}
// SigningRoot calculates the signing root of the given header.
func (f Forks) SigningRoot(header Header) (common.Hash, error) {
domain, err := f.domain(header.Epoch())
if err != nil {
return common.Hash{}, err
}
var (
signingRoot common.Hash
headerHash = header.Hash()
hasher = sha256.New()
)
hasher.Write(headerHash[:])
hasher.Write(domain[:])
hasher.Sum(signingRoot[:0])
return signingRoot, nil
}
func (f Forks) Len() int { return len(f) }
func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
func (f Forks) Less(i, j int) bool { return f[i].Epoch < f[j].Epoch }
// ChainConfig contains the beacon chain configuration.
type ChainConfig struct {
GenesisTime uint64 // Unix timestamp of slot 0
GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation
Forks Forks
}
// AddFork adds a new item to the list of forks.
func (c *ChainConfig) AddFork(name string, epoch uint64, version []byte) *ChainConfig {
fork := &Fork{
Name: name,
Epoch: epoch,
Version: version,
}
fork.computeDomain(c.GenesisValidatorsRoot)
c.Forks = append(c.Forks, fork)
sort.Sort(c.Forks)
return c
}
// LoadForks parses the beacon chain configuration file (config.yaml) and extracts
// the list of forks.
func (c *ChainConfig) LoadForks(path string) error {
file, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("failed to read beacon chain config file: %v", err)
}
config := make(map[string]string)
if err := yaml.Unmarshal(file, &config); err != nil {
return fmt.Errorf("failed to parse beacon chain config file: %v", err)
}
var (
versions = make(map[string][]byte)
epochs = make(map[string]uint64)
)
epochs["GENESIS"] = 0
for key, value := range config {
if strings.HasSuffix(key, "_FORK_VERSION") {
name := key[:len(key)-len("_FORK_VERSION")]
if v, err := hexutil.Decode(value); err == nil {
versions[name] = v
} else {
return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", value, err)
}
}
if strings.HasSuffix(key, "_FORK_EPOCH") {
name := key[:len(key)-len("_FORK_EPOCH")]
if v, err := strconv.ParseUint(value, 10, 64); err == nil {
epochs[name] = v
} else {
return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", value, err)
}
}
}
for name, epoch := range epochs {
if version, ok := versions[name]; ok {
delete(versions, name)
c.AddFork(name, epoch, version)
} else {
return fmt.Errorf("fork id missing for %q in beacon chain config file", name)
}
}
for name := range versions {
return fmt.Errorf("epoch number missing for fork %q in beacon chain config file", name)
}
sort.Sort(c.Forks)
return nil
}

View File

@@ -0,0 +1,66 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package types
import (
"encoding/json"
"errors"
"github.com/ethereum/go-ethereum/common"
)
var _ = (*headerMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
Slot common.Decimal `gencodec:"required" json:"slot"`
ProposerIndex common.Decimal `gencodec:"required" json:"proposer_index"`
ParentRoot common.Hash `gencodec:"required" json:"parent_root"`
StateRoot common.Hash `gencodec:"required" json:"state_root"`
BodyRoot common.Hash `gencodec:"required" json:"body_root"`
}
var enc Header
enc.Slot = common.Decimal(h.Slot)
enc.ProposerIndex = common.Decimal(h.ProposerIndex)
enc.ParentRoot = h.ParentRoot
enc.StateRoot = h.StateRoot
enc.BodyRoot = h.BodyRoot
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (h *Header) UnmarshalJSON(input []byte) error {
type Header struct {
Slot *common.Decimal `gencodec:"required" json:"slot"`
ProposerIndex *common.Decimal `gencodec:"required" json:"proposer_index"`
ParentRoot *common.Hash `gencodec:"required" json:"parent_root"`
StateRoot *common.Hash `gencodec:"required" json:"state_root"`
BodyRoot *common.Hash `gencodec:"required" json:"body_root"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Slot == nil {
return errors.New("missing required field 'slot' for Header")
}
h.Slot = uint64(*dec.Slot)
if dec.ProposerIndex == nil {
return errors.New("missing required field 'proposer_index' for Header")
}
h.ProposerIndex = uint64(*dec.ProposerIndex)
if dec.ParentRoot == nil {
return errors.New("missing required field 'parent_root' for Header")
}
h.ParentRoot = *dec.ParentRoot
if dec.StateRoot == nil {
return errors.New("missing required field 'state_root' for Header")
}
h.StateRoot = *dec.StateRoot
if dec.BodyRoot == nil {
return errors.New("missing required field 'body_root' for Header")
}
h.BodyRoot = *dec.BodyRoot
return nil
}

View File

@@ -0,0 +1,51 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package types
import (
"encoding/json"
"errors"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var _ = (*syncAggregateMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (s SyncAggregate) MarshalJSON() ([]byte, error) {
type SyncAggregate struct {
Signers hexutil.Bytes `gencodec:"required" json:"sync_committee_bits"`
Signature hexutil.Bytes `gencodec:"required" json:"sync_committee_signature"`
}
var enc SyncAggregate
enc.Signers = s.Signers[:]
enc.Signature = s.Signature[:]
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (s *SyncAggregate) UnmarshalJSON(input []byte) error {
type SyncAggregate struct {
Signers *hexutil.Bytes `gencodec:"required" json:"sync_committee_bits"`
Signature *hexutil.Bytes `gencodec:"required" json:"sync_committee_signature"`
}
var dec SyncAggregate
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Signers == nil {
return errors.New("missing required field 'sync_committee_bits' for SyncAggregate")
}
if len(*dec.Signers) != len(s.Signers) {
return errors.New("field 'sync_committee_bits' has wrong length, need 64 items")
}
copy(s.Signers[:], *dec.Signers)
if dec.Signature == nil {
return errors.New("missing required field 'sync_committee_signature' for SyncAggregate")
}
if len(*dec.Signature) != len(s.Signature) {
return errors.New("field 'sync_committee_signature' has wrong length, need 96 items")
}
copy(s.Signature[:], *dec.Signature)
return nil
}

121
beacon/types/header.go Normal file
View File

@@ -0,0 +1,121 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package types implements a few types of the beacon chain for light client usage.
package types
import (
"crypto/sha256"
"encoding/binary"
"github.com/ethereum/go-ethereum/beacon/merkle"
"github.com/ethereum/go-ethereum/beacon/params"
"github.com/ethereum/go-ethereum/common"
)
//go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go
const (
headerIndexSlot = 8
headerIndexProposerIndex = 9
headerIndexParentRoot = 10
headerIndexStateRoot = 11
headerIndexBodyRoot = 12
)
// Header defines a beacon header.
//
// See data structure definition here:
// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader
type Header struct {
// Monotonically increasing slot number for the beacon block (may be gapped)
Slot uint64 `gencodec:"required" json:"slot"`
// Index into the validator table who created the beacon block
ProposerIndex uint64 `gencodec:"required" json:"proposer_index"`
// SSZ hash of the parent beacon header
ParentRoot common.Hash `gencodec:"required" json:"parent_root"`
// SSZ hash of the beacon state (https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#beacon-state)
StateRoot common.Hash `gencodec:"required" json:"state_root"`
// SSZ hash of the beacon block body (https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#beaconblockbody)
BodyRoot common.Hash `gencodec:"required" json:"body_root"`
}
// headerMarshaling is a field type overrides for gencodec.
type headerMarshaling struct {
Slot common.Decimal
ProposerIndex common.Decimal
}
// Hash calculates the block root of the header.
//
// TODO(zsfelfoldi): Remove this when an SSZ encoder lands.
func (h *Header) Hash() common.Hash {
var values [16]merkle.Value // values corresponding to indices 8 to 15 of the beacon header tree
binary.LittleEndian.PutUint64(values[headerIndexSlot][:8], h.Slot)
binary.LittleEndian.PutUint64(values[headerIndexProposerIndex][:8], h.ProposerIndex)
values[headerIndexParentRoot] = merkle.Value(h.ParentRoot)
values[headerIndexStateRoot] = merkle.Value(h.StateRoot)
values[headerIndexBodyRoot] = merkle.Value(h.BodyRoot)
hasher := sha256.New()
for i := 7; i > 0; i-- {
hasher.Reset()
hasher.Write(values[i*2][:])
hasher.Write(values[i*2+1][:])
hasher.Sum(values[i][:0])
}
return common.Hash(values[1])
}
// Epoch returns the epoch the header belongs to.
func (h *Header) Epoch() uint64 {
return h.Slot / params.EpochLength
}
// SyncPeriod returns the sync period the header belongs to.
func (h *Header) SyncPeriod() uint64 {
return SyncPeriod(h.Slot)
}
// SyncPeriodStart returns the first slot of the given period.
func SyncPeriodStart(period uint64) uint64 {
return period * params.SyncPeriodLength
}
// SyncPeriod returns the sync period that the given slot belongs to.
func SyncPeriod(slot uint64) uint64 {
return slot / params.SyncPeriodLength
}
// SignedHeader represents a beacon header signed by a sync committee.
//
// This structure is created from either an optimistic update or an instant update:
// - https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate
// - https://github.com/zsfelfoldi/beacon-APIs/blob/instant_update/apis/beacon/light_client/instant_update.yaml
type SignedHeader struct {
// Beacon header being signed
Header Header
// Sync committee BLS signature aggregate
Signature SyncAggregate
// Slot in which the signature has been created (newer than Header.Slot,
// determines the signing sync committee)
SignatureSlot uint64
}

136
beacon/types/light_sync.go Normal file
View File

@@ -0,0 +1,136 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package types
import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/beacon/merkle"
"github.com/ethereum/go-ethereum/beacon/params"
"github.com/ethereum/go-ethereum/common"
)
// BootstrapData contains a sync committee where light sync can be started,
// together with a proof through a beacon header and corresponding state.
// Note: BootstrapData is fetched from a server based on a known checkpoint hash.
type BootstrapData struct {
Header Header
CommitteeRoot common.Hash
Committee *SerializedSyncCommittee `rlp:"-"`
CommitteeBranch merkle.Values
}
// Validate verifies the proof included in BootstrapData.
func (c *BootstrapData) Validate() error {
if c.CommitteeRoot != c.Committee.Root() {
return errors.New("wrong committee root")
}
return merkle.VerifyProof(c.Header.StateRoot, params.StateIndexSyncCommittee, c.CommitteeBranch, merkle.Value(c.CommitteeRoot))
}
// LightClientUpdate is a proof of the next sync committee root based on a header
// signed by the sync committee of the given period. Optionally, the update can
// prove quasi-finality by the signed header referring to a previous, finalized
// header from the same period, and the finalized header referring to the next
// sync committee root.
//
// See data structure definition here:
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientupdate
type LightClientUpdate struct {
AttestedHeader SignedHeader // Arbitrary header out of the period signed by the sync committee
NextSyncCommitteeRoot common.Hash // Sync committee of the next period advertised in the current one
NextSyncCommitteeBranch merkle.Values // Proof for the next period's sync committee
FinalizedHeader *Header `rlp:"nil"` // Optional header to announce a point of finality
FinalityBranch merkle.Values // Proof for the announced finality
score *UpdateScore // Weight of the update to compare between competing ones
}
// Validate verifies the validity of the update.
func (update *LightClientUpdate) Validate() error {
period := update.AttestedHeader.Header.SyncPeriod()
if SyncPeriod(update.AttestedHeader.SignatureSlot) != period {
return errors.New("signature slot and signed header are from different periods")
}
if update.FinalizedHeader != nil {
if update.FinalizedHeader.SyncPeriod() != period {
return errors.New("finalized header is from different period")
}
if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexFinalBlock, update.FinalityBranch, merkle.Value(update.FinalizedHeader.Hash())); err != nil {
return fmt.Errorf("invalid finalized header proof: %w", err)
}
}
if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexNextSyncCommittee, update.NextSyncCommitteeBranch, merkle.Value(update.NextSyncCommitteeRoot)); err != nil {
return fmt.Errorf("invalid next sync committee proof: %w", err)
}
return nil
}
// Score returns the UpdateScore describing the proof strength of the update
// Note: thread safety can be ensured by always calling Score on a newly received
// or decoded update before making it potentially available for other threads
func (update *LightClientUpdate) Score() UpdateScore {
if update.score == nil {
update.score = &UpdateScore{
SignerCount: uint32(update.AttestedHeader.Signature.SignerCount()),
SubPeriodIndex: uint32(update.AttestedHeader.Header.Slot & 0x1fff),
FinalizedHeader: update.FinalizedHeader != nil,
}
}
return *update.score
}
// UpdateScore allows the comparison between updates at the same period in order
// to find the best update chain that provides the strongest proof of being canonical.
//
// UpdateScores have a tightly packed binary encoding format for efficient p2p
// protocol transmission. Each UpdateScore is encoded in 3 bytes.
// When interpreted as a 24 bit little indian unsigned integer:
// - the lowest 10 bits contain the number of signers in the header signature aggregate
// - the next 13 bits contain the "sub-period index" which is he signed header's
// slot modulo params.SyncPeriodLength (which is correlated with the risk of the chain being
// re-orged before the previous period boundary in case of non-finalized updates)
// - the highest bit is set when the update is finalized (meaning that the finality
// header referenced by the signed header is in the same period as the signed
// header, making reorgs before the period boundary impossible
type UpdateScore struct {
SignerCount uint32 // number of signers in the header signature aggregate
SubPeriodIndex uint32 // signed header's slot modulo params.SyncPeriodLength
FinalizedHeader bool // update is considered finalized if has finalized header from the same period and 2/3 signatures
}
// finalized returns true if the update has a header signed by at least 2/3 of
// the committee, referring to a finalized header that refers to the next sync
// committee. This condition is a close approximation of the actual finality
// condition that can only be verified by full beacon nodes.
func (u *UpdateScore) finalized() bool {
return u.FinalizedHeader && u.SignerCount >= params.SyncCommitteeSupermajority
}
// BetterThan returns true if update u is considered better than w.
func (u UpdateScore) BetterThan(w UpdateScore) bool {
var (
uFinalized = u.finalized()
wFinalized = w.finalized()
)
if uFinalized != wFinalized {
return uFinalized
}
return u.SignerCount > w.SignerCount
}

View File

@@ -1,20 +1,30 @@
# This file contains sha256 checksums of optional build dependencies.
8e486e8e85a281fc5ce3f0bedc5b9d2dbf6276d7db0b25d3ec034f313da0375f go1.19.5.src.tar.gz
23d22bb6571bbd60197bee8aaa10e702f9802786c2e2ddce5c84527e86b66aa0 go1.19.5.darwin-amd64.tar.gz
4a67f2bf0601afe2177eb58f825adf83509511d77ab79174db0712dc9efa16c8 go1.19.5.darwin-arm64.tar.gz
b18a5e1e60130003896e1d1c8a9e142c7cccf6f5063d52c55dd42006434419c1 go1.19.5.freebsd-386.tar.gz
317996f7427691ff3a7ffd1b6aa089b9c66cd76f32e9107443f2f6aad1bb568a go1.19.5.freebsd-amd64.tar.gz
f68331aa7458a3598060595f5601d5731fd452bb2c62ff23095ddad68854e510 go1.19.5.linux-386.tar.gz
36519702ae2fd573c9869461990ae550c8c0d955cd28d2827a6b159fda81ff95 go1.19.5.linux-amd64.tar.gz
fc0aa29c933cec8d76f5435d859aaf42249aa08c74eb2d154689ae44c08d23b3 go1.19.5.linux-arm64.tar.gz
ec14f04bdaf4a62bdcf8b55b9b6434cc27c2df7d214d0bb7076a7597283b026a go1.19.5.linux-armv6l.tar.gz
e4032e7c52ebc48bad5c58ba8de0759b6091d9b1e59581a8a521c8c9d88dbe93 go1.19.5.linux-ppc64le.tar.gz
764871cbca841a99a24e239b63c68a4aaff4104658e3165e9ca450cac1fcbea3 go1.19.5.linux-s390x.tar.gz
8873f5871d996106b701febd979c5af022e6ea58bdbbb3817a28ab948b22c286 go1.19.5.windows-386.zip
167db91a2e40aeb453d3e59d213ecab06f62e1c4a84d13a06ccda1d999961caa go1.19.5.windows-amd64.zip
85a75555e82d8aa6f486d8d29491c593389682acce9f0c270090d5938eee30ef go1.19.5.windows-arm64.zip
# version:spec-tests 1.0.6
# https://github.com/ethereum/execution-spec-tests/releases
# https://github.com/ethereum/execution-spec-tests/releases/download/v1.0.6/
485af7b66cf41eb3a8c1bd46632913b8eb95995df867cf665617bbc9b4beedd1 fixtures_develop.tar.gz
# version:golang 1.21.5
# https://go.dev/dl/
285cbbdf4b6e6e62ed58f370f3f6d8c30825d6e56c5853c66d3c23bcdb09db19 go1.21.5.src.tar.gz
a2e1d5743e896e5fe1e7d96479c0a769254aed18cf216cf8f4c3a2300a9b3923 go1.21.5.darwin-amd64.tar.gz
d0f8ac0c4fb3efc223a833010901d02954e3923cfe2c9a2ff0e4254a777cc9cc go1.21.5.darwin-arm64.tar.gz
2c05bbe0dc62456b90b7ddd354a54f373b7c377a98f8b22f52ab694b4f6cca58 go1.21.5.freebsd-386.tar.gz
30b6c64e9a77129605bc12f836422bf09eec577a8c899ee46130aeff81567003 go1.21.5.freebsd-amd64.tar.gz
8f4dba9cf5c61757bbd7e9ebdb93b6a30a1b03f4a636a1ba0cc2f27b907ab8e1 go1.21.5.linux-386.tar.gz
e2bc0b3e4b64111ec117295c088bde5f00eeed1567999ff77bc859d7df70078e go1.21.5.linux-amd64.tar.gz
841cced7ecda9b2014f139f5bab5ae31785f35399f236b8b3e75dff2a2978d96 go1.21.5.linux-arm64.tar.gz
837f4bf4e22fcdf920ffeaa4abf3d02d1314e03725431065f4d44c46a01b42fe go1.21.5.linux-armv6l.tar.gz
907b8c6ec4be9b184952e5d3493be66b1746442394a8bc78556c56834cd7c38b go1.21.5.linux-ppc64le.tar.gz
9c4a81b72ebe44368813cd03684e1080a818bf915d84163abae2ed325a1b2dc0 go1.21.5.linux-s390x.tar.gz
6da2418889dfb37763d0eb149c4a8d728c029e12f0cd54fbca0a31ae547e2d34 go1.21.5.windows-386.zip
bbe603cde7c9dee658f45164b4d06de1eff6e6e6b800100824e7c00d56a9a92f go1.21.5.windows-amd64.zip
9b7acca50e674294e43202df4fbc26d5af4d8bc3170a3342a1514f09a2dab5e9 go1.21.5.windows-arm64.zip
# version:golangci 1.51.1
# https://github.com/golangci/golangci-lint/releases/
# https://github.com/golangci/golangci-lint/releases/download/v1.51.1/
fba08acc4027f69f07cef48fbff70b8a7ecdfaa1c2aba9ad3fb31d60d9f5d4bc golangci-lint-1.51.1-darwin-amd64.tar.gz
75b8f0ff3a4e68147156be4161a49d4576f1be37a0b506473f8c482140c1e7f2 golangci-lint-1.51.1-darwin-arm64.tar.gz
e06b3459aaed356e1667580be00b05f41f3b2e29685d12cdee571c23e1edb414 golangci-lint-1.51.1-freebsd-386.tar.gz
@@ -41,3 +51,14 @@ c4f58b7e227b9fd41f0e9310dc83f4a4e7d026598e2f6e95b78761081a6d9bd2 golangci-lint-
eb57f9bcb56646f2e3d6ccaf02ec227815fb05077b2e0b1bf9e755805acdc2b9 golangci-lint-1.51.1-windows-arm64.zip
bce02f7232723cb727755ee11f168a700a00896a25d37f87c4b173bce55596b4 golangci-lint-1.51.1-windows-armv6.zip
cf6403f84707ce8c98664736772271bc8874f2e760c2fd0f00cf3e85963507e9 golangci-lint-1.51.1-windows-armv7.zip
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
#
# This version is fine to be old and full of security holes, we just use it
# to build the latest Go. Don't change it. If it ever becomes insufficient,
# we need to switch over to a recursive builder to jump across supported
# versions.
#
# version:ppa-builder 1.19.6
# https://go.dev/dl/
d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz

View File

@@ -120,15 +120,15 @@ var (
// Distros for which packages are created.
// Note: vivid is unsupported because there is no golang-1.6 package for it.
// Note: the following Ubuntu releases have been officially deprecated on Launchpad:
// wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish
// wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish,
// kinetic
debDistroGoBoots = map[string]string{
"trusty": "golang-1.11", // EOL: 04/2024
"xenial": "golang-go", // EOL: 04/2026
"bionic": "golang-go", // EOL: 04/2028
"focal": "golang-go", // EOL: 04/2030
"jammy": "golang-go", // EOL: 04/2032
"kinetic": "golang-go", // EOL: 07/2023
//"lunar": "golang-go", // EOL: 01/2024
"trusty": "golang-1.11", // EOL: 04/2024
"xenial": "golang-go", // EOL: 04/2026
"bionic": "golang-go", // EOL: 04/2028
"focal": "golang-go", // EOL: 04/2030
"jammy": "golang-go", // EOL: 04/2032
"lunar": "golang-go", // EOL: 01/2024
}
debGoBootPaths = map[string]string{
@@ -136,10 +136,8 @@ var (
"golang-go": "/usr/lib/go",
}
// This is the version of go that will be downloaded by
//
// go run ci.go install -dlgo
dlgoVersion = "1.19.5"
// This is where the tests should be unpacked.
executionSpecTestsDir = "tests/spec-tests"
)
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@@ -177,6 +175,8 @@ func main() {
doWindowsInstaller(os.Args[2:])
case "purge":
doPurge(os.Args[2:])
case "sanitycheck":
doSanityCheck()
default:
log.Fatal("unknown command ", os.Args[1])
}
@@ -192,19 +192,23 @@ func doInstall(cmdline []string) {
staticlink = flag.Bool("static", false, "Create statically-linked executable")
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
// Configure the toolchain.
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
if *dlgo {
csdb := build.MustLoadChecksums("build/checksums.txt")
tc.Root = build.DownloadGo(csdb, dlgoVersion)
tc.Root = build.DownloadGo(csdb)
}
// Disable CLI markdown doc generation in release builds.
buildTags := []string{"urfave_cli_no_docs"}
// Enable linking the CKZG library since we can make it work with additional flags.
if env.UbuntuVersion != "trusty" {
buildTags = append(buildTags, "ckzg")
}
// Configure the build.
env := build.Env()
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
// arm64 CI builders are memory-constrained and can't handle concurrent builds,
@@ -213,7 +217,6 @@ func doInstall(cmdline []string) {
if env.CI && runtime.GOARCH == "arm64" {
gobuild.Args = append(gobuild.Args, "-p", "1")
}
// We use -trimpath to avoid leaking local paths into the built executables.
gobuild.Args = append(gobuild.Args, "-trimpath")
@@ -282,17 +285,31 @@ func doTest(cmdline []string) {
coverage = flag.Bool("coverage", false, "Whether to record code coverage")
verbose = flag.Bool("v", false, "Whether to log verbosely")
race = flag.Bool("race", false, "Execute the race detector")
short = flag.Bool("short", false, "Pass the 'short'-flag to go test")
cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads")
)
flag.CommandLine.Parse(cmdline)
// Get test fixtures.
csdb := build.MustLoadChecksums("build/checksums.txt")
downloadSpecTestFixtures(csdb, *cachedir)
// Configure the toolchain.
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
if *dlgo {
csdb := build.MustLoadChecksums("build/checksums.txt")
tc.Root = build.DownloadGo(csdb, dlgoVersion)
tc.Root = build.DownloadGo(csdb)
}
gotest := tc.Go("test")
// CI needs a bit more time for the statetests (default 10m).
gotest.Args = append(gotest.Args, "-timeout=20m")
// Enable CKZG backend in CI.
gotest.Args = append(gotest.Args, "-tags=ckzg")
// Enable integration-tests
gotest.Args = append(gotest.Args, "-tags=integrationtests")
// Test a single package at a time. CI builders are slow
// and some tests run into timeouts under load.
gotest.Args = append(gotest.Args, "-p", "1")
@@ -305,6 +322,9 @@ func doTest(cmdline []string) {
if *race {
gotest.Args = append(gotest.Args, "-race")
}
if *short {
gotest.Args = append(gotest.Args, "-short")
}
packages := []string{"./..."}
if len(flag.CommandLine.Args()) > 0 {
@@ -314,6 +334,25 @@ func doTest(cmdline []string) {
build.MustRun(gotest)
}
// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string {
executionSpecTestsVersion, err := build.Version(csdb, "spec-tests")
if err != nil {
log.Fatal(err)
}
ext := ".tar.gz"
base := "fixtures_develop" // TODO(MariusVanDerWijden) rename once the version becomes part of the filename
url := fmt.Sprintf("https://github.com/ethereum/execution-spec-tests/releases/download/v%s/%s%s", executionSpecTestsVersion, base, ext)
archivePath := filepath.Join(cachedir, base+ext)
if err := csdb.DownloadFile(url, archivePath); err != nil {
log.Fatal(err)
}
if err := build.ExtractArchive(archivePath, executionSpecTestsDir); err != nil {
log.Fatal(err)
}
return filepath.Join(cachedir, base)
}
// doLint runs golangci-lint on requested packages.
func doLint(cmdline []string) {
var (
@@ -327,15 +366,17 @@ func doLint(cmdline []string) {
linter := downloadLinter(*cachedir)
lflags := []string{"run", "--config", ".golangci.yml"}
build.MustRunCommand(linter, append(lflags, packages...)...)
build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
fmt.Println("You have achieved perfection.")
}
// downloadLinter downloads and unpacks golangci-lint.
func downloadLinter(cachedir string) string {
const version = "1.51.1"
csdb := build.MustLoadChecksums("build/checksums.txt")
version, err := build.Version(csdb, "golangci")
if err != nil {
log.Fatal(err)
}
arch := runtime.GOARCH
ext := ".tar.gz"
@@ -457,10 +498,6 @@ func maybeSkipArchive(env build.Environment) {
log.Printf("skipping archive creation because this is a PR build")
os.Exit(0)
}
if env.IsCronJob {
log.Printf("skipping archive creation because this is a cron job")
os.Exit(0)
}
if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
log.Printf("skipping archive creation because branch %q, tag %q is not on the inclusion list", env.Branch, env.Tag)
os.Exit(0)
@@ -655,10 +692,11 @@ func doDebianSource(cmdline []string) {
gpg.Stdin = bytes.NewReader(key)
build.MustRun(gpg)
}
// Download and verify the Go source package.
gobundle := downloadGoSources(*cachedir)
// Download and verify the Go source packages.
var (
gobootbundle = downloadGoBootstrapSources(*cachedir)
gobundle = downloadGoSources(*cachedir)
)
// Download all the dependencies needed to build the sources and run the ci script
srcdepfetch := tc.Go("mod", "download")
srcdepfetch.Env = append(srcdepfetch.Env, "GOPATH="+filepath.Join(*workdir, "modgopath"))
@@ -675,12 +713,19 @@ func doDebianSource(cmdline []string) {
meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables)
pkgdir := stageDebianSource(*workdir, meta)
// Add Go source code
// Add bootstrapper Go source code
if err := build.ExtractArchive(gobootbundle, pkgdir); err != nil {
log.Fatalf("Failed to extract bootstrapper Go sources: %v", err)
}
if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".goboot")); err != nil {
log.Fatalf("Failed to rename bootstrapper Go source folder: %v", err)
}
// Add builder Go source code
if err := build.ExtractArchive(gobundle, pkgdir); err != nil {
log.Fatalf("Failed to extract Go sources: %v", err)
log.Fatalf("Failed to extract builder Go sources: %v", err)
}
if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil {
log.Fatalf("Failed to rename Go source folder: %v", err)
log.Fatalf("Failed to rename builder Go source folder: %v", err)
}
// Add all dependency modules in compressed form
os.MkdirAll(filepath.Join(pkgdir, ".mod", "cache"), 0755)
@@ -709,9 +754,30 @@ func doDebianSource(cmdline []string) {
}
}
// downloadGoBootstrapSources downloads the Go source tarball that will be used
// to bootstrap the builder Go.
func downloadGoBootstrapSources(cachedir string) string {
csdb := build.MustLoadChecksums("build/checksums.txt")
gobootVersion, err := build.Version(csdb, "ppa-builder")
if err != nil {
log.Fatal(err)
}
file := fmt.Sprintf("go%s.src.tar.gz", gobootVersion)
url := "https://dl.google.com/go/" + file
dst := filepath.Join(cachedir, file)
if err := csdb.DownloadFile(url, dst); err != nil {
log.Fatal(err)
}
return dst
}
// downloadGoSources downloads the Go source tarball.
func downloadGoSources(cachedir string) string {
csdb := build.MustLoadChecksums("build/checksums.txt")
dlgoVersion, err := build.Version(csdb, "golang")
if err != nil {
log.Fatal(err)
}
file := fmt.Sprintf("go%s.src.tar.gz", dlgoVersion)
url := "https://dl.google.com/go/" + file
dst := filepath.Join(cachedir, file)
@@ -1038,3 +1104,7 @@ func doPurge(cmdline []string) {
log.Fatal(err)
}
}
func doSanityCheck() {
build.DownloadAndVerifyChecksums(build.MustLoadChecksums("build/checksums.txt"))
}

View File

@@ -16,7 +16,11 @@ override_dh_auto_build:
# We can't download a fresh Go within Launchpad, so we're shipping and building
# one on the fly. However, we can't build it inside the go-ethereum folder as
# bootstrapping clashes with go modules, so build in a sibling folder.
(mv .go ../ && cd ../.go/src && ./make.bash)
#
# We're also shipping the bootstrapper as of Go 1.20 as it had minimum version
# requirements opposed to older versions of Go.
(mv .goboot ../ && cd ../.goboot/src && ./make.bash)
(mv .go ../ && cd ../.go/src && GOROOT_BOOTSTRAP=`pwd`/../../.goboot ./make.bash)
# We can't download external go modules within Launchpad, so we're shipping the
# entire dependency source cache with go-ethereum.
@@ -24,7 +28,7 @@ override_dh_auto_build:
mv .mod $(GOPATH)/pkg/mod
# A fresh Go was built, all dependency downloads faked, hope build works now
../.go/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}}
../.go/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}} -ubuntu {{.Distro}}
override_dh_auto_test:

View File

@@ -46,12 +46,13 @@ import (
"path/filepath"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"text/template"
"time"
"golang.org/x/exp/slices"
)
var (
@@ -64,10 +65,8 @@ var (
"vendor/", "tests/testdata/", "build/",
// don't relicense vendored sources
"cmd/internal/browser",
"common/bitutil/bitutil",
"common/prque/",
"consensus/ethash/xor.go",
"crypto/blake2b/",
"crypto/bn256/",
"crypto/bls12381/",
@@ -77,6 +76,7 @@ var (
"log/",
"metrics/",
"signer/rules/deps",
"internal/reexec",
// skip special licenses
"crypto/secp256k1", // Relicensed to BSD-3 via https://github.com/ethereum/go-ethereum/pull/17225
@@ -152,13 +152,6 @@ func (i info) gpl() bool {
return false
}
// authors implements the sort.Interface for strings in case-insensitive mode.
type authors []string
func (as authors) Len() int { return len(as) }
func (as authors) Less(i, j int) bool { return strings.ToLower(as[i]) < strings.ToLower(as[j]) }
func (as authors) Swap(i, j int) { as[i], as[j] = as[j], as[i] }
func main() {
var (
files = getFiles()
@@ -299,7 +292,9 @@ func writeAuthors(files []string) {
}
}
// Write sorted list of authors back to the file.
sort.Sort(authors(list))
slices.SortFunc(list, func(a, b string) bool {
return strings.ToLower(a) < strings.ToLower(b)
})
content := new(bytes.Buffer)
content.WriteString(authorsFileHeader)
for _, a := range list {

View File

@@ -232,7 +232,7 @@ func abigen(c *cli.Context) error {
}
func main() {
log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)

View File

@@ -8,6 +8,7 @@ import (
)
func TestNameFilter(t *testing.T) {
t.Parallel()
_, err := newNameFilter("Foo")
require.Error(t, err)
_, err = newNameFilter("too/many:colons:Foo")

View File

@@ -23,6 +23,7 @@ import (
"fmt"
"net"
"os"
"time"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/crypto"
@@ -43,7 +44,7 @@ func main() {
natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|pmp:<IP>|extip:<IP>)")
netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)")
runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode")
verbosity = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-5)")
verbosity = flag.Int("verbosity", 3, "log verbosity (0-5)")
vmodule = flag.String("vmodule", "", "log verbosity pattern")
nodeKey *ecdsa.PrivateKey
@@ -51,10 +52,11 @@ func main() {
)
flag.Parse()
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
glogger.Verbosity(log.Lvl(*verbosity))
glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
slogVerbosity := log.FromLegacyLevel(*verbosity)
glogger.Verbosity(slogVerbosity)
glogger.Vmodule(*vmodule)
log.Root().SetHandler(glogger)
log.SetDefault(log.NewLogger(glogger))
natm, err := nat.Parse(*natdesc)
if err != nil {
@@ -107,21 +109,20 @@ func main() {
if err != nil {
utils.Fatalf("-ListenUDP: %v", err)
}
realaddr := conn.LocalAddr().(*net.UDPAddr)
if natm != nil {
if !realaddr.IP.IsLoopback() {
go nat.Map(natm, nil, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
}
if ext, err := natm.ExternalIP(); err == nil {
realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
}
}
printNotice(&nodeKey.PublicKey, *realaddr)
defer conn.Close()
db, _ := enode.OpenDB("")
ln := enode.NewLocalNode(db, nodeKey)
listenerAddr := conn.LocalAddr().(*net.UDPAddr)
if natm != nil && !listenerAddr.IP.IsLoopback() {
natAddr := doPortMapping(natm, ln, listenerAddr)
if natAddr != nil {
listenerAddr = natAddr
}
}
printNotice(&nodeKey.PublicKey, *listenerAddr)
cfg := discover.Config{
PrivateKey: nodeKey,
NetRestrict: restrictList,
@@ -148,3 +149,61 @@ func printNotice(nodeKey *ecdsa.PublicKey, addr net.UDPAddr) {
fmt.Println("Note: you're using cmd/bootnode, a developer tool.")
fmt.Println("We recommend using a regular node as bootstrap node for production deployments.")
}
func doPortMapping(natm nat.Interface, ln *enode.LocalNode, addr *net.UDPAddr) *net.UDPAddr {
const (
protocol = "udp"
name = "ethereum discovery"
)
newLogger := func(external int, internal int) log.Logger {
return log.New("proto", protocol, "extport", external, "intport", internal, "interface", natm)
}
var (
intport = addr.Port
extaddr = &net.UDPAddr{IP: addr.IP, Port: addr.Port}
mapTimeout = nat.DefaultMapTimeout
log = newLogger(addr.Port, intport)
)
addMapping := func() {
// Get the external address.
var err error
extaddr.IP, err = natm.ExternalIP()
if err != nil {
log.Debug("Couldn't get external IP", "err", err)
return
}
// Create the mapping.
p, err := natm.AddMapping(protocol, extaddr.Port, intport, name, mapTimeout)
if err != nil {
log.Debug("Couldn't add port mapping", "err", err)
return
}
if p != uint16(extaddr.Port) {
extaddr.Port = int(p)
log = newLogger(extaddr.Port, intport)
log.Info("NAT mapped alternative port")
} else {
log.Info("NAT mapped port")
}
// Update IP/port information of the local node.
ln.SetStaticIP(extaddr.IP)
ln.SetFallbackUDP(extaddr.Port)
}
// Perform mapping once, synchronously.
log.Info("Attempting port mapping")
addMapping()
// Refresh the mapping periodically.
go func() {
refresh := time.NewTimer(mapTimeout)
defer refresh.Stop()
for range refresh.C {
addMapping()
refresh.Reset(mapTimeout)
}
}()
return extaddr
}

View File

@@ -1,103 +0,0 @@
## Checkpoint-admin
Checkpoint-admin is a tool for updating checkpoint oracle status. It provides a series of functions including deploying checkpoint oracle contract, signing for new checkpoints, and updating checkpoints in the checkpoint oracle contract.
### Checkpoint
In the LES protocol, there is an important concept called checkpoint. In simple terms, whenever a certain number of blocks are generated on the blockchain, a new checkpoint is generated which contains some important information such as
* Block hash at checkpoint
* Canonical hash trie root at checkpoint
* Bloom trie root at checkpoint
*For a more detailed introduction to checkpoint, please see the LES [spec](https://github.com/ethereum/devp2p/blob/master/caps/les.md).*
Using this information, light clients can skip all historical block headers when synchronizing data and start synchronization from this checkpoint. Therefore, as long as the light client can obtain some latest and correct checkpoints, the amount of data and time for synchronization will be greatly reduced.
However, from a security perspective, the most critical step in a synchronization algorithm based on checkpoints is to determine whether the checkpoint used by the light client is correct. Otherwise, all blockchain data synchronized based on this checkpoint may be wrong. For this we provide two different ways to ensure the correctness of the checkpoint used by the light client.
#### Hardcoded checkpoint
There are several hardcoded checkpoints in the [source code](https://github.com/ethereum/go-ethereum/blob/master/params/config.go#L38) of the go-ethereum project. These checkpoints are updated by go-ethereum developers when new versions of software are released. Because light client users trust Geth developers to some extent, hardcoded checkpoints in the code can also be considered correct.
#### Checkpoint oracle
Hardcoded checkpoints can solve the problem of verifying the correctness of checkpoints (although this is a more centralized solution). But the pain point of this solution is that developers can only update checkpoints when a new version of software is released. In addition, light client users usually do not keep the Geth version they use always up to date. So hardcoded checkpoints used by users are generally stale. Therefore, it still needs to download a large amount of blockchain data during synchronization.
Checkpoint oracle is a more flexible solution. In simple terms, this is a smart contract that is deployed on the blockchain. The smart contract records several designated trusted signers. Whenever enough trusted signers have issued their signatures for the same checkpoint, it can be considered that the checkpoint has been authenticated by the signers. Checkpoints authenticated by trusted signers can be considered correct.
So this way, even without updating the software version, as long as the trusted signers regularly update the checkpoint in oracle on time, the light client can always use the latest and verified checkpoint for data synchronization.
### Usage
Checkpoint-admin is a command line tool designed for checkpoint oracle. Users can easily deploy contracts and update checkpoints through this tool.
#### Install
```shell
go get github.com/ethereum/go-ethereum/cmd/checkpoint-admin
```
#### Deploy
Deploy checkpoint oracle contract. `--signers` indicates the specified trusted signer, and `--threshold` indicates the minimum number of signatures required by trusted signers to update a checkpoint.
```shell
checkpoint-admin deploy --rpc <NODE_RPC_ENDPOINT> --clef <CLEF_ENDPOINT> --signer <SIGNER_TO_SIGN_TX> --signers <TRUSTED_SIGNER_LIST> --threshold 1
```
It is worth noting that checkpoint-admin only supports clef as a signer for transactions and plain text(checkpoint). For more clef usage, please see the clef [tutorial](https://geth.ethereum.org/docs/clef/tutorial) .
#### Sign
Checkpoint-admin provides two different modes of signing. You can automatically obtain the current stable checkpoint and sign it interactively, and you can also use the information provided by the command line flags to sign checkpoint offline.
**Interactive mode**
```shell
checkpoint-admin sign --clef <CLEF_ENDPOINT> --signer <SIGNER_TO_SIGN_CHECKPOINT> --rpc <NODE_RPC_ENDPOINT>
```
*It is worth noting that the connected Geth node can be a fullnode or a light client. If it is fullnode, you must enable the LES protocol. E.G. add `--light.serv 50` to the startup command line flags*.
**Offline mode**
```shell
checkpoint-admin sign --clef <CLEF_ENDPOINT> --signer <SIGNER_TO_SIGN_CHECKPOINT> --index <CHECKPOINT_INDEX> --hash <CHECKPOINT_HASH> --oracle <CHECKPOINT_ORACLE_ADDRESS>
```
*CHECKPOINT_HASH is obtained based on this [calculation method](https://github.com/ethereum/go-ethereum/blob/master/params/config.go#L251).*
#### Publish
Collect enough signatures from different trusted signers for the same checkpoint and submit them to oracle to update the "authenticated" checkpoint in the contract.
```shell
checkpoint-admin publish --clef <CLEF_ENDPOINT> --rpc <NODE_RPC_ENDPOINT> --signer <SIGNER_TO_SIGN_TX> --index <CHECKPOINT_INDEX> --signatures <CHECKPOINT_SIGNATURE_LIST>
```
#### Status query
Check the latest status of checkpoint oracle.
```shell
checkpoint-admin status --rpc <NODE_RPC_ENDPOINT>
```
### Enable checkpoint oracle in your private network
Currently, only the Ethereum mainnet and the default supported test networks (rinkeby, goerli) activate this feature. If you want to activate this feature in your private network, you can overwrite the relevant checkpoint oracle settings through the configuration file after deploying the oracle contract.
* Get your node configuration file `geth dumpconfig OTHER_COMMAND_LINE_OPTIONS > config.toml`
* Edit the configuration file and add the following information
```toml
[Eth.CheckpointOracle]
Address = CHECKPOINT_ORACLE_ADDRESS
Signers = [TRUSTED_SIGNER_1, ..., TRUSTED_SIGNER_N]
Threshold = THRESHOLD
```
* Start geth with the modified configuration file
*In the private network, all fullnodes and light clients need to be started using the same checkpoint oracle settings.*

View File

@@ -1,120 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum 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.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"strconv"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/external"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts/checkpointoracle"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/urfave/cli/v2"
)
// newClient creates a client with specified remote URL.
func newClient(ctx *cli.Context) *ethclient.Client {
client, err := ethclient.Dial(ctx.String(nodeURLFlag.Name))
if err != nil {
utils.Fatalf("Failed to connect to Ethereum node: %v", err)
}
return client
}
// newRPCClient creates a rpc client with specified node URL.
func newRPCClient(url string) *rpc.Client {
client, err := rpc.Dial(url)
if err != nil {
utils.Fatalf("Failed to connect to Ethereum node: %v", err)
}
return client
}
// getContractAddr retrieves the register contract address through
// rpc request.
func getContractAddr(client *rpc.Client) common.Address {
var addr string
if err := client.Call(&addr, "les_getCheckpointContractAddress"); err != nil {
utils.Fatalf("Failed to fetch checkpoint oracle address: %v", err)
}
return common.HexToAddress(addr)
}
// getCheckpoint retrieves the specified checkpoint or the latest one
// through rpc request.
func getCheckpoint(ctx *cli.Context, client *rpc.Client) *params.TrustedCheckpoint {
var checkpoint *params.TrustedCheckpoint
if ctx.IsSet(indexFlag.Name) {
var result [3]string
index := uint64(ctx.Int64(indexFlag.Name))
if err := client.Call(&result, "les_getCheckpoint", index); err != nil {
utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err)
}
checkpoint = &params.TrustedCheckpoint{
SectionIndex: index,
SectionHead: common.HexToHash(result[0]),
CHTRoot: common.HexToHash(result[1]),
BloomRoot: common.HexToHash(result[2]),
}
} else {
var result [4]string
err := client.Call(&result, "les_latestCheckpoint")
if err != nil {
utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err)
}
index, err := strconv.ParseUint(result[0], 0, 64)
if err != nil {
utils.Fatalf("Failed to parse checkpoint index %v", err)
}
checkpoint = &params.TrustedCheckpoint{
SectionIndex: index,
SectionHead: common.HexToHash(result[1]),
CHTRoot: common.HexToHash(result[2]),
BloomRoot: common.HexToHash(result[3]),
}
}
return checkpoint
}
// newContract creates a registrar contract instance with specified
// contract address or the default contracts for mainnet or testnet.
func newContract(client *rpc.Client) (common.Address, *checkpointoracle.CheckpointOracle) {
addr := getContractAddr(client)
if addr == (common.Address{}) {
utils.Fatalf("No specified registrar contract address")
}
contract, err := checkpointoracle.NewCheckpointOracle(addr, ethclient.NewClient(client))
if err != nil {
utils.Fatalf("Failed to setup registrar contract %s: %v", addr, err)
}
return addr, contract
}
// newClefSigner sets up a clef backend and returns a clef transaction signer.
func newClefSigner(ctx *cli.Context) *bind.TransactOpts {
clef, err := external.NewExternalSigner(ctx.String(clefURLFlag.Name))
if err != nil {
utils.Fatalf("Failed to create clef signer %v", err)
}
return bind.NewClefTransactor(clef, accounts.Account{Address: common.HexToAddress(ctx.String(signerFlag.Name))})
}

View File

@@ -1,311 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum 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.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"math/big"
"strings"
"time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/contracts/checkpointoracle"
"github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/urfave/cli/v2"
)
var commandDeploy = &cli.Command{
Name: "deploy",
Usage: "Deploy a new checkpoint oracle contract",
Flags: []cli.Flag{
nodeURLFlag,
clefURLFlag,
signerFlag,
signersFlag,
thresholdFlag,
},
Action: deploy,
}
var commandSign = &cli.Command{
Name: "sign",
Usage: "Sign the checkpoint with the specified key",
Flags: []cli.Flag{
nodeURLFlag,
clefURLFlag,
signerFlag,
indexFlag,
hashFlag,
oracleFlag,
},
Action: sign,
}
var commandPublish = &cli.Command{
Name: "publish",
Usage: "Publish a checkpoint into the oracle",
Flags: []cli.Flag{
nodeURLFlag,
clefURLFlag,
signerFlag,
indexFlag,
signaturesFlag,
},
Action: publish,
}
// deploy deploys the checkpoint registrar contract.
//
// Note the network where the contract is deployed depends on
// the network where the connected node is located.
func deploy(ctx *cli.Context) error {
// Gather all the addresses that should be permitted to sign
var addrs []common.Address
for _, account := range strings.Split(ctx.String(signersFlag.Name), ",") {
if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
utils.Fatalf("Invalid account in --signers: '%s'", trimmed)
}
addrs = append(addrs, common.HexToAddress(account))
}
// Retrieve and validate the signing threshold
needed := ctx.Int(thresholdFlag.Name)
if needed == 0 || needed > len(addrs) {
utils.Fatalf("Invalid signature threshold %d", needed)
}
// Print a summary to ensure the user understands what they're signing
fmt.Printf("Deploying new checkpoint oracle:\n\n")
for i, addr := range addrs {
fmt.Printf("Admin %d => %s\n", i+1, addr.Hex())
}
fmt.Printf("\nSignatures needed to publish: %d\n", needed)
// setup clef signer, create an abigen transactor and an RPC client
transactor, client := newClefSigner(ctx), newClient(ctx)
// Deploy the checkpoint oracle
fmt.Println("Sending deploy request to Clef...")
oracle, tx, _, err := contract.DeployCheckpointOracle(transactor, client, addrs, big.NewInt(int64(params.CheckpointFrequency)),
big.NewInt(int64(params.CheckpointProcessConfirmations)), big.NewInt(int64(needed)))
if err != nil {
utils.Fatalf("Failed to deploy checkpoint oracle %v", err)
}
log.Info("Deployed checkpoint oracle", "address", oracle, "tx", tx.Hash().Hex())
return nil
}
// sign creates the signature for specific checkpoint
// with local key. Only contract admins have the permission to
// sign checkpoint.
func sign(ctx *cli.Context) error {
var (
offline bool // The indicator whether we sign checkpoint by offline.
chash common.Hash
cindex uint64
address common.Address
node *rpc.Client
oracle *checkpointoracle.CheckpointOracle
)
if !ctx.IsSet(nodeURLFlag.Name) {
// Offline mode signing
offline = true
if !ctx.IsSet(hashFlag.Name) {
utils.Fatalf("Please specify the checkpoint hash (--hash) to sign in offline mode")
}
chash = common.HexToHash(ctx.String(hashFlag.Name))
if !ctx.IsSet(indexFlag.Name) {
utils.Fatalf("Please specify checkpoint index (--index) to sign in offline mode")
}
cindex = ctx.Uint64(indexFlag.Name)
if !ctx.IsSet(oracleFlag.Name) {
utils.Fatalf("Please specify oracle address (--oracle) to sign in offline mode")
}
address = common.HexToAddress(ctx.String(oracleFlag.Name))
} else {
// Interactive mode signing, retrieve the data from the remote node
node = newRPCClient(ctx.String(nodeURLFlag.Name))
checkpoint := getCheckpoint(ctx, node)
chash, cindex, address = checkpoint.Hash(), checkpoint.SectionIndex, getContractAddr(node)
// Check the validity of checkpoint
reqCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
defer cancelFn()
head, err := ethclient.NewClient(node).HeaderByNumber(reqCtx, nil)
if err != nil {
return err
}
num := head.Number.Uint64()
if num < ((cindex+1)*params.CheckpointFrequency + params.CheckpointProcessConfirmations) {
utils.Fatalf("Invalid future checkpoint")
}
_, oracle = newContract(node)
latest, _, h, err := oracle.Contract().GetLatestCheckpoint(nil)
if err != nil {
return err
}
if cindex < latest {
utils.Fatalf("Checkpoint is too old")
}
if cindex == latest && (latest != 0 || h.Uint64() != 0) {
utils.Fatalf("Stale checkpoint, latest registered %d, given %d", latest, cindex)
}
}
var (
signature string
signer string
)
// isAdmin checks whether the specified signer is admin.
isAdmin := func(addr common.Address) error {
signers, err := oracle.Contract().GetAllAdmin(nil)
if err != nil {
return err
}
for _, s := range signers {
if s == addr {
return nil
}
}
return fmt.Errorf("signer %v is not the admin", addr.Hex())
}
// Print to the user the data thy are about to sign
fmt.Printf("Oracle => %s\n", address.Hex())
fmt.Printf("Index %4d => %s\n", cindex, chash.Hex())
// Sign checkpoint in clef mode.
signer = ctx.String(signerFlag.Name)
if !offline {
if err := isAdmin(common.HexToAddress(signer)); err != nil {
return err
}
}
clef := newRPCClient(ctx.String(clefURLFlag.Name))
p := make(map[string]string)
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, cindex)
p["address"] = address.Hex()
p["message"] = hexutil.Encode(append(buf, chash.Bytes()...))
fmt.Println("Sending signing request to Clef...")
if err := clef.Call(&signature, "account_signData", accounts.MimetypeDataWithValidator, signer, p); err != nil {
utils.Fatalf("Failed to sign checkpoint, err %v", err)
}
fmt.Printf("Signer => %s\n", signer)
fmt.Printf("Signature => %s\n", signature)
return nil
}
// sighash calculates the hash of the data to sign for the checkpoint oracle.
func sighash(index uint64, oracle common.Address, hash common.Hash) []byte {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, index)
data := append([]byte{0x19, 0x00}, append(oracle[:], append(buf, hash[:]...)...)...)
return crypto.Keccak256(data)
}
// ecrecover calculates the sender address from a sighash and signature combo.
func ecrecover(sighash []byte, sig []byte) common.Address {
sig[64] -= 27
defer func() { sig[64] += 27 }()
signer, err := crypto.SigToPub(sighash, sig)
if err != nil {
utils.Fatalf("Failed to recover sender from signature %x: %v", sig, err)
}
return crypto.PubkeyToAddress(*signer)
}
// publish registers the specified checkpoint which generated by connected node
// with a authorised private key.
func publish(ctx *cli.Context) error {
// Print the checkpoint oracle's current status to make sure we're interacting
// with the correct network and contract.
status(ctx)
// Gather the signatures from the CLI
var sigs [][]byte
for _, sig := range strings.Split(ctx.String(signaturesFlag.Name), ",") {
trimmed := strings.TrimPrefix(strings.TrimSpace(sig), "0x")
if len(trimmed) != 130 {
utils.Fatalf("Invalid signature in --signature: '%s'", trimmed)
} else {
sigs = append(sigs, common.Hex2Bytes(trimmed))
}
}
// Retrieve the checkpoint we want to sign to sort the signatures
var (
client = newRPCClient(ctx.String(nodeURLFlag.Name))
addr, oracle = newContract(client)
checkpoint = getCheckpoint(ctx, client)
sighash = sighash(checkpoint.SectionIndex, addr, checkpoint.Hash())
)
for i := 0; i < len(sigs); i++ {
for j := i + 1; j < len(sigs); j++ {
signerA := ecrecover(sighash, sigs[i])
signerB := ecrecover(sighash, sigs[j])
if bytes.Compare(signerA.Bytes(), signerB.Bytes()) > 0 {
sigs[i], sigs[j] = sigs[j], sigs[i]
}
}
}
// Retrieve recent header info to protect replay attack
reqCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
defer cancelFn()
head, err := ethclient.NewClient(client).HeaderByNumber(reqCtx, nil)
if err != nil {
return err
}
num := head.Number.Uint64()
recent, err := ethclient.NewClient(client).HeaderByNumber(reqCtx, big.NewInt(int64(num-128)))
if err != nil {
return err
}
// Print a summary of the operation that's going to be performed
fmt.Printf("Publishing %d => %s:\n\n", checkpoint.SectionIndex, checkpoint.Hash().Hex())
for i, sig := range sigs {
fmt.Printf("Signer %d => %s\n", i+1, ecrecover(sighash, sig).Hex())
}
fmt.Println()
fmt.Printf("Sentry number => %d\nSentry hash => %s\n", recent.Number, recent.Hash().Hex())
// Publish the checkpoint into the oracle
fmt.Println("Sending publish request to Clef...")
tx, err := oracle.RegisterCheckpoint(newClefSigner(ctx), checkpoint.SectionIndex, checkpoint.Hash().Bytes(), recent.Number, recent.Hash(), sigs)
if err != nil {
utils.Fatalf("Register contract failed %v", err)
}
log.Info("Successfully registered checkpoint", "tx", tx.Hash().Hex())
return nil
}

View File

@@ -1,96 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum 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.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
// checkpoint-admin is a utility that can be used to query checkpoint information
// and register stable checkpoints into an oracle contract.
package main
import (
"fmt"
"os"
"github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
)
var app = flags.NewApp("ethereum checkpoint helper tool")
func init() {
app.Commands = []*cli.Command{
commandStatus,
commandDeploy,
commandSign,
commandPublish,
}
app.Flags = []cli.Flag{
oracleFlag,
nodeURLFlag,
}
}
// Commonly used command line flags.
var (
indexFlag = &cli.Int64Flag{
Name: "index",
Usage: "Checkpoint index (query latest from remote node if not specified)",
}
hashFlag = &cli.StringFlag{
Name: "hash",
Usage: "Checkpoint hash (query latest from remote node if not specified)",
}
oracleFlag = &cli.StringFlag{
Name: "oracle",
Usage: "Checkpoint oracle address (query from remote node if not specified)",
}
thresholdFlag = &cli.Int64Flag{
Name: "threshold",
Usage: "Minimal number of signatures required to approve a checkpoint",
}
nodeURLFlag = &cli.StringFlag{
Name: "rpc",
Value: "http://localhost:8545",
Usage: "The rpc endpoint of a local or remote geth node",
}
clefURLFlag = &cli.StringFlag{
Name: "clef",
Value: "http://localhost:8550",
Usage: "The rpc endpoint of clef",
}
signerFlag = &cli.StringFlag{
Name: "signer",
Usage: "Signer address for clef signing",
}
signersFlag = &cli.StringFlag{
Name: "signers",
Usage: "Comma separated accounts of trusted checkpoint signers",
}
signaturesFlag = &cli.StringFlag{
Name: "signatures",
Usage: "Comma separated checkpoint signatures to submit",
}
)
func main() {
log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
fdlimit.Raise(2048)
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

View File

@@ -1,60 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum 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.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"
)
var commandStatus = &cli.Command{
Name: "status",
Usage: "Fetches the signers and checkpoint status of the oracle contract",
Flags: []cli.Flag{
nodeURLFlag,
},
Action: status,
}
// status fetches the admin list of specified registrar contract.
func status(ctx *cli.Context) error {
// Create a wrapper around the checkpoint oracle contract
addr, oracle := newContract(newRPCClient(ctx.String(nodeURLFlag.Name)))
fmt.Printf("Oracle => %s\n", addr.Hex())
fmt.Println()
// Retrieve the list of authorized signers (admins)
admins, err := oracle.Contract().GetAllAdmin(nil)
if err != nil {
return err
}
for i, admin := range admins {
fmt.Printf("Admin %d => %s\n", i+1, admin.Hex())
}
fmt.Println()
// Retrieve the latest checkpoint
index, checkpoint, height, err := oracle.Contract().GetLatestCheckpoint(nil)
if err != nil {
return err
}
fmt.Printf("Checkpoint (published at #%d) %d => %s\n", height, index, common.Hash(checkpoint).Hex())
return nil
}

View File

@@ -2,7 +2,7 @@
Clef can be used to sign transactions and data and is meant as a(n eventual) replacement for Geth's account management. This allows DApps to not depend on Geth's account management. When a DApp wants to sign data (or a transaction), it can send the content to Clef, which will then provide the user with context and asks for permission to sign the content. If the users grants the signing request, Clef will send the signature back to the DApp.
This setup allows a DApp to connect to a remote Ethereum node and send transactions that are locally signed. This can help in situations when a DApp is connected to an untrusted remote Ethereum node, because a local one is not available, not synchronised with the chain, or is a node that has no built-in (or limited) account management.
This setup allows a DApp to connect to a remote Ethereum node and send transactions that are locally signed. This can help in situations when a DApp is connected to an untrusted remote Ethereum node, because a local one is not available, not synchronized with the chain, or is a node that has no built-in (or limited) account management.
Clef can run as a daemon on the same machine, off a usb-stick like [USB armory](https://inversepath.com/usbarmory), or even a separate VM in a [QubesOS](https://www.qubes-os.org/) type setup.
@@ -29,7 +29,7 @@ GLOBAL OPTIONS:
--loglevel value log level to emit to the screen (default: 4)
--keystore value Directory for the keystore (default: "$HOME/.ethereum/keystore")
--configdir value Directory for Clef configuration (default: "$HOME/.clef")
--chainid value Chain id to use for signing (1=mainnet, 4=Rinkeby, 5=Goerli) (default: 1)
--chainid value Chain id to use for signing (1=mainnet, 5=Goerli) (default: 1)
--lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength
--nousb Disables monitoring for and managing USB hardware wallets
--pcscdpath value Path to the smartcard daemon (pcscd) socket file (default: "/run/pcscd/pcscd.comm")

View File

@@ -26,12 +26,13 @@ import (
// TestImportRaw tests clef --importraw
func TestImportRaw(t *testing.T) {
t.Parallel()
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Cleanup(func() { os.Remove(keyPath) })
t.Parallel()
t.Run("happy-path", func(t *testing.T) {
t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword")
@@ -43,6 +44,7 @@ func TestImportRaw(t *testing.T) {
})
// tests clef --importraw with mismatched passwords.
t.Run("pw-mismatch", func(t *testing.T) {
t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword1").input("myverylongpassword2").WaitExit()
@@ -52,6 +54,7 @@ func TestImportRaw(t *testing.T) {
})
// tests clef --importraw with a too short password.
t.Run("short-pw", func(t *testing.T) {
t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("shorty").input("shorty").WaitExit()
@@ -64,12 +67,13 @@ func TestImportRaw(t *testing.T) {
// TestListAccounts tests clef --list-accounts
func TestListAccounts(t *testing.T) {
t.Parallel()
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Cleanup(func() { os.Remove(keyPath) })
t.Parallel()
t.Run("no-accounts", func(t *testing.T) {
t.Parallel()
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-accounts")
if out := string(clef.Output()); !strings.Contains(out, "The keystore is empty.") {
t.Logf("Output\n%v", out)
@@ -77,6 +81,7 @@ func TestListAccounts(t *testing.T) {
}
})
t.Run("one-account", func(t *testing.T) {
t.Parallel()
// First, we need to import
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword").WaitExit()
@@ -91,12 +96,13 @@ func TestListAccounts(t *testing.T) {
// TestListWallets tests clef --list-wallets
func TestListWallets(t *testing.T) {
t.Parallel()
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Cleanup(func() { os.Remove(keyPath) })
t.Parallel()
t.Run("no-accounts", func(t *testing.T) {
t.Parallel()
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-wallets")
if out := string(clef.Output()); !strings.Contains(out, "There are no wallets.") {
t.Logf("Output\n%v", out)
@@ -104,6 +110,7 @@ func TestListWallets(t *testing.T) {
}
})
t.Run("one-account", func(t *testing.T) {
t.Parallel()
// First, we need to import
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword").WaitExit()

View File

@@ -27,6 +27,7 @@ import (
"fmt"
"io"
"math/big"
"net"
"os"
"os/signal"
"path/filepath"
@@ -99,7 +100,7 @@ var (
chainIdFlag = &cli.Int64Flag{
Name: "chainid",
Value: params.MainnetChainConfig.ChainID.Int64(),
Usage: "Chain id to use for signing (1=mainnet, 4=Rinkeby, 5=Goerli)",
Usage: "Chain id to use for signing (1=mainnet, 5=Goerli)",
}
rpcPortFlag = &cli.IntFlag{
Name: "http.port",
@@ -326,7 +327,7 @@ func initializeSecrets(c *cli.Context) error {
return err
}
if num != len(masterSeed) {
return fmt.Errorf("failed to read enough random")
return errors.New("failed to read enough random")
}
n, p := keystore.StandardScryptN, keystore.StandardScryptP
if c.Bool(utils.LightKDFFlag.Name) {
@@ -482,7 +483,7 @@ func initialize(c *cli.Context) error {
}
} else if !c.Bool(acceptFlag.Name) {
if !confirm(legalWarning) {
return fmt.Errorf("aborted by user")
return errors.New("aborted by user")
}
fmt.Println()
}
@@ -491,7 +492,8 @@ func initialize(c *cli.Context) error {
if usecolor {
output = colorable.NewColorable(logOutput)
}
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int(logLevelFlag.Name)), log.StreamHandler(output, log.TerminalFormat(usecolor))))
verbosity := log.FromLegacyLevel(c.Int(logLevelFlag.Name))
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(output, verbosity, usecolor)))
return nil
}
@@ -580,6 +582,7 @@ func accountImport(c *cli.Context) error {
return err
}
if first != second {
//lint:ignore ST1005 This is a message for the user
return errors.New("Passwords do not match")
}
acc, err := internalApi.ImportRawKey(hex.EncodeToString(crypto.FromECDSA(pKey)), first)
@@ -590,7 +593,7 @@ func accountImport(c *cli.Context) error {
Address %v
Keystore file: %v
The key is now encrypted; losing the password will result in permanently losing
The key is now encrypted; losing the password will result in permanently losing
access to the key and all associated funds!
Make sure to backup keystore and passwords in a safe location.`,
@@ -732,6 +735,7 @@ func signer(c *cli.Context) error {
cors := utils.SplitAndTrim(c.String(utils.HTTPCORSDomainFlag.Name))
srv := rpc.NewServer()
srv.SetBatchLimits(node.DefaultConfig.BatchRequestLimit, node.DefaultConfig.BatchResponseMaxSize)
err := node.RegisterApis(rpcAPI, []string{"account"}, srv)
if err != nil {
utils.Fatalf("Could not register API: %w", err)
@@ -742,7 +746,7 @@ func signer(c *cli.Context) error {
port := c.Int(rpcPortFlag.Name)
// start http server
httpEndpoint := fmt.Sprintf("%s:%d", c.String(utils.HTTPListenAddrFlag.Name), port)
httpEndpoint := net.JoinHostPort(c.String(utils.HTTPListenAddrFlag.Name), fmt.Sprintf("%d", port))
httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, rpc.DefaultHTTPTimeouts, handler)
if err != nil {
utils.Fatalf("Could not start RPC api: %v", err)
@@ -844,7 +848,7 @@ func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
}
masterSeed, err := decryptSeed(cipherKey, password)
if err != nil {
return nil, fmt.Errorf("failed to decrypt the master seed of clef")
return nil, errors.New("failed to decrypt the master seed of clef")
}
if len(masterSeed) < 256 {
return nil, fmt.Errorf("master seed of insufficient length, expected >255 bytes, got %d", len(masterSeed))
@@ -1204,7 +1208,7 @@ func GenDoc(ctx *cli.Context) error {
URL: accounts.URL{Path: ".. ignored .."},
},
{
Address: common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff"),
Address: common.MaxAddress,
},
}})
}

View File

@@ -91,7 +91,7 @@ class StdIOHandler:
{"jsonrpc":"2.0","id":20,"method":"ui_approveTx","params":[{"transaction":{"from":"0xDEADbEeF000000000000000000000000DeaDbeEf","to":"0xDEADbEeF000000000000000000000000DeaDbeEf","gas":"0x3e8","gasPrice":"0x5","maxFeePerGas":null,"maxPriorityFeePerGas":null,"value":"0x6","nonce":"0x1","data":"0x"},"call_info":null,"meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]}
:param transaction: transaction info
:param call_info: info abou the call, e.g. if ABI info could not be
:param call_info: info about the call, e.g. if ABI info could not be
:param meta: metadata about the request, e.g. where the call comes from
:return:
""" # noqa: E501

View File

@@ -21,8 +21,8 @@ import (
"os"
"testing"
"github.com/docker/docker/pkg/reexec"
"github.com/ethereum/go-ethereum/internal/cmdtest"
"github.com/ethereum/go-ethereum/internal/reexec"
)
const registeredName = "clef-test"

View File

@@ -44,7 +44,7 @@ set to standard output. The following filters are supported:
- `-limit <N>` limits the output set to N entries, taking the top N nodes by score
- `-ip <CIDR>` filters nodes by IP subnet
- `-min-age <duration>` filters nodes by 'first seen' time
- `-eth-network <mainnet/rinkeby/goerli/sepolia>` filters nodes by "eth" ENR entry
- `-eth-network <mainnet/goerli/sepolia/holesky>` filters nodes by "eth" ENR entry
- `-les-server` filters nodes by LES server support
- `-snap` filters nodes by snap protocol support

View File

@@ -17,6 +17,9 @@
package main
import (
"errors"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/log"
@@ -34,6 +37,7 @@ type crawler struct {
// settings
revalidateInterval time.Duration
mu sync.RWMutex
}
const (
@@ -48,7 +52,14 @@ type resolver interface {
RequestENR(*enode.Node) (*enode.Node, error)
}
func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler {
func newCrawler(input nodeSet, bootnodes []*enode.Node, disc resolver, iters ...enode.Iterator) (*crawler, error) {
if len(input) == 0 {
input.add(bootnodes...)
}
if len(input) == 0 {
return nil, errors.New("no input nodes to start crawling")
}
c := &crawler{
input: input,
output: make(nodeSet, len(input)),
@@ -64,10 +75,10 @@ func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler
for id, n := range input {
c.output[id] = n
}
return c
return c, nil
}
func (c *crawler) run(timeout time.Duration) nodeSet {
func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
var (
timeoutTimer = time.NewTimer(timeout)
timeoutCh <-chan time.Time
@@ -75,35 +86,51 @@ func (c *crawler) run(timeout time.Duration) nodeSet {
doneCh = make(chan enode.Iterator, len(c.iters))
liveIters = len(c.iters)
)
if nthreads < 1 {
nthreads = 1
}
defer timeoutTimer.Stop()
defer statusTicker.Stop()
for _, it := range c.iters {
go c.runIterator(doneCh, it)
}
var (
added int
updated int
skipped int
recent int
removed int
added atomic.Uint64
updated atomic.Uint64
skipped atomic.Uint64
recent atomic.Uint64
removed atomic.Uint64
wg sync.WaitGroup
)
wg.Add(nthreads)
for i := 0; i < nthreads; i++ {
go func() {
defer wg.Done()
for {
select {
case n := <-c.ch:
switch c.updateNode(n) {
case nodeSkipIncompat:
skipped.Add(1)
case nodeSkipRecent:
recent.Add(1)
case nodeRemoved:
removed.Add(1)
case nodeAdded:
added.Add(1)
default:
updated.Add(1)
}
case <-c.closed:
return
}
}
}()
}
loop:
for {
select {
case n := <-c.ch:
switch c.updateNode(n) {
case nodeSkipIncompat:
skipped++
case nodeSkipRecent:
recent++
case nodeRemoved:
removed++
case nodeAdded:
added++
default:
updated++
}
case it := <-doneCh:
if it == c.inputIter {
// Enable timeout when we're done revalidating the input nodes.
@@ -119,8 +146,11 @@ loop:
break loop
case <-statusTicker.C:
log.Info("Crawling in progress",
"added", added, "updated", updated, "removed", removed,
"ignored(recent)", recent, "ignored(incompatible)", skipped)
"added", added.Load(),
"updated", updated.Load(),
"removed", removed.Load(),
"ignored(recent)", recent.Load(),
"ignored(incompatible)", skipped.Load())
}
}
@@ -131,6 +161,7 @@ loop:
for ; liveIters > 0; liveIters-- {
<-doneCh
}
wg.Wait()
return c.output
}
@@ -148,7 +179,9 @@ func (c *crawler) runIterator(done chan<- enode.Iterator, it enode.Iterator) {
// updateNode updates the info about the given node, and returns a status
// about what changed
func (c *crawler) updateNode(n *enode.Node) int {
c.mu.RLock()
node, ok := c.output[n.ID()]
c.mu.RUnlock()
// Skip validation of recently-seen nodes.
if ok && time.Since(node.LastCheck) < c.revalidateInterval {
@@ -156,10 +189,9 @@ func (c *crawler) updateNode(n *enode.Node) int {
}
// Request the node record.
nn, err := c.disc.RequestENR(n)
node.LastCheck = truncNow()
status := nodeUpdated
if err != nil {
node.LastCheck = truncNow()
if nn, err := c.disc.RequestENR(n); err != nil {
if node.Score == 0 {
// Node doesn't implement EIP-868.
log.Debug("Skipping node", "id", n.ID())
@@ -176,8 +208,9 @@ func (c *crawler) updateNode(n *enode.Node) int {
}
node.LastResponse = node.LastCheck
}
// Store/update node in output set.
c.mu.Lock()
defer c.mu.Unlock()
if node.Score <= 0 {
log.Debug("Removing node", "id", n.ID())
delete(c.output, n.ID())

View File

@@ -17,6 +17,7 @@
package main
import (
"errors"
"fmt"
"net"
"strconv"
@@ -78,7 +79,7 @@ var (
Name: "crawl",
Usage: "Updates a nodes.json file with random nodes found in the DHT",
Action: discv4Crawl,
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag}),
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}),
}
discv4TestCommand = &cli.Command{
Name: "test",
@@ -120,6 +121,11 @@ var (
Usage: "Time limit for the crawl.",
Value: 30 * time.Minute,
}
crawlParallelismFlag = &cli.IntFlag{
Name: "parallel",
Usage: "How many parallel discoveries to attempt.",
Value: 16,
}
remoteEnodeFlag = &cli.StringFlag{
Name: "remote",
Usage: "Enode of the remote node under test",
@@ -137,7 +143,7 @@ var discoveryNodeFlags = []cli.Flag{
func discv4Ping(ctx *cli.Context) error {
n := getNodeArg(ctx)
disc := startV4(ctx)
disc, _ := startV4(ctx)
defer disc.Close()
start := time.Now()
@@ -150,7 +156,7 @@ func discv4Ping(ctx *cli.Context) error {
func discv4RequestRecord(ctx *cli.Context) error {
n := getNodeArg(ctx)
disc := startV4(ctx)
disc, _ := startV4(ctx)
defer disc.Close()
respN, err := disc.RequestENR(n)
@@ -163,7 +169,7 @@ func discv4RequestRecord(ctx *cli.Context) error {
func discv4Resolve(ctx *cli.Context) error {
n := getNodeArg(ctx)
disc := startV4(ctx)
disc, _ := startV4(ctx)
defer disc.Close()
fmt.Println(disc.Resolve(n).String())
@@ -172,7 +178,7 @@ func discv4Resolve(ctx *cli.Context) error {
func discv4ResolveJSON(ctx *cli.Context) error {
if ctx.NArg() < 1 {
return fmt.Errorf("need nodes file as argument")
return errors.New("need nodes file as argument")
}
nodesFile := ctx.Args().Get(0)
inputSet := make(nodeSet)
@@ -190,31 +196,38 @@ func discv4ResolveJSON(ctx *cli.Context) error {
nodeargs = append(nodeargs, n)
}
// Run the crawler.
disc := startV4(ctx)
disc, config := startV4(ctx)
defer disc.Close()
c := newCrawler(inputSet, disc, enode.IterNodes(nodeargs))
c, err := newCrawler(inputSet, config.Bootnodes, disc, enode.IterNodes(nodeargs))
if err != nil {
return err
}
c.revalidateInterval = 0
output := c.run(0)
output := c.run(0, 1)
writeNodesJSON(nodesFile, output)
return nil
}
func discv4Crawl(ctx *cli.Context) error {
if ctx.NArg() < 1 {
return fmt.Errorf("need nodes file as argument")
return errors.New("need nodes file as argument")
}
nodesFile := ctx.Args().First()
var inputSet nodeSet
inputSet := make(nodeSet)
if common.FileExist(nodesFile) {
inputSet = loadNodesJSON(nodesFile)
}
disc := startV4(ctx)
disc, config := startV4(ctx)
defer disc.Close()
c := newCrawler(inputSet, disc, disc.RandomNodes())
c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes())
if err != nil {
return err
}
c.revalidateInterval = 10 * time.Minute
output := c.run(ctx.Duration(crawlTimeoutFlag.Name))
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
writeNodesJSON(nodesFile, output)
return nil
}
@@ -223,7 +236,7 @@ func discv4Crawl(ctx *cli.Context) error {
func discv4Test(ctx *cli.Context) error {
// Configure test package globals.
if !ctx.IsSet(remoteEnodeFlag.Name) {
return fmt.Errorf("Missing -%v", remoteEnodeFlag.Name)
return fmt.Errorf("missing -%v", remoteEnodeFlag.Name)
}
v4test.Remote = ctx.String(remoteEnodeFlag.Name)
v4test.Listen1 = ctx.String(testListen1Flag.Name)
@@ -232,14 +245,14 @@ func discv4Test(ctx *cli.Context) error {
}
// startV4 starts an ephemeral discovery V4 node.
func startV4(ctx *cli.Context) *discover.UDPv4 {
func startV4(ctx *cli.Context) (*discover.UDPv4, discover.Config) {
ln, config := makeDiscoveryConfig(ctx)
socket := listen(ctx, ln)
disc, err := discover.ListenV4(socket, ln, config)
if err != nil {
exit(err)
}
return disc
return disc, config
}
func makeDiscoveryConfig(ctx *cli.Context) (*enode.LocalNode, discover.Config) {
@@ -331,7 +344,7 @@ func listen(ctx *cli.Context, ln *enode.LocalNode) *net.UDPConn {
}
func parseBootnodes(ctx *cli.Context) ([]*enode.Node, error) {
s := params.RinkebyBootnodes
s := params.MainnetBootnodes
if ctx.IsSet(bootnodesFlag.Name) {
input := ctx.String(bootnodesFlag.Name)
if input == "" {

View File

@@ -17,6 +17,7 @@
package main
import (
"errors"
"fmt"
"time"
@@ -80,7 +81,7 @@ var (
func discv5Ping(ctx *cli.Context) error {
n := getNodeArg(ctx)
disc := startV5(ctx)
disc, _ := startV5(ctx)
defer disc.Close()
fmt.Println(disc.Ping(n))
@@ -89,7 +90,7 @@ func discv5Ping(ctx *cli.Context) error {
func discv5Resolve(ctx *cli.Context) error {
n := getNodeArg(ctx)
disc := startV5(ctx)
disc, _ := startV5(ctx)
defer disc.Close()
fmt.Println(disc.Resolve(n))
@@ -98,19 +99,23 @@ func discv5Resolve(ctx *cli.Context) error {
func discv5Crawl(ctx *cli.Context) error {
if ctx.NArg() < 1 {
return fmt.Errorf("need nodes file as argument")
return errors.New("need nodes file as argument")
}
nodesFile := ctx.Args().First()
var inputSet nodeSet
inputSet := make(nodeSet)
if common.FileExist(nodesFile) {
inputSet = loadNodesJSON(nodesFile)
}
disc := startV5(ctx)
disc, config := startV5(ctx)
defer disc.Close()
c := newCrawler(inputSet, disc, disc.RandomNodes())
c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes())
if err != nil {
return err
}
c.revalidateInterval = 10 * time.Minute
output := c.run(ctx.Duration(crawlTimeoutFlag.Name))
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
writeNodesJSON(nodesFile, output)
return nil
}
@@ -126,7 +131,7 @@ func discv5Test(ctx *cli.Context) error {
}
func discv5Listen(ctx *cli.Context) error {
disc := startV5(ctx)
disc, _ := startV5(ctx)
defer disc.Close()
fmt.Println(disc.Self())
@@ -134,12 +139,12 @@ func discv5Listen(ctx *cli.Context) error {
}
// startV5 starts an ephemeral discovery v5 node.
func startV5(ctx *cli.Context) *discover.UDPv5 {
func startV5(ctx *cli.Context) (*discover.UDPv5, discover.Config) {
ln, config := makeDiscoveryConfig(ctx)
socket := listen(ctx, ln)
disc, err := discover.ListenV5(socket, ln, config)
if err != nil {
exit(err)
}
return disc
return disc, config
}

View File

@@ -18,6 +18,7 @@ package main
import (
"context"
"errors"
"fmt"
"strings"
@@ -48,7 +49,7 @@ type cloudflareClient struct {
func newCloudflareClient(ctx *cli.Context) *cloudflareClient {
token := ctx.String(cloudflareTokenFlag.Name)
if token == "" {
exit(fmt.Errorf("need cloudflare API token to proceed"))
exit(errors.New("need cloudflare API token to proceed"))
}
api, err := cloudflare.NewWithAPIToken(token)
if err != nil {
@@ -113,7 +114,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
records = lrecords
log.Info(fmt.Sprintf("Retrieving existing TXT records on %s", name))
entries, err := c.DNSRecords(context.Background(), c.zoneID, cloudflare.DNSRecord{Type: "TXT"})
entries, _, err := c.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), cloudflare.ListDNSRecordsParams{Type: "TXT"})
if err != nil {
return err
}
@@ -126,40 +127,62 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
}
// Iterate over the new records and inject anything missing.
log.Info("Updating DNS entries")
created := 0
updated := 0
skipped := 0
for path, val := range records {
old, exists := existing[path]
if !exists {
// Entry is unknown, push a new one to Cloudflare.
log.Info(fmt.Sprintf("Creating %s = %q", path, val))
log.Debug(fmt.Sprintf("Creating %s = %q", path, val))
created++
ttl := rootTTL
if path != name {
ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare
}
record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}
_, err = c.CreateDNSRecord(context.Background(), c.zoneID, record)
record := cloudflare.CreateDNSRecordParams{Type: "TXT", Name: path, Content: val, TTL: ttl}
_, err = c.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record)
} else if old.Content != val {
// Entry already exists, only change its content.
log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val))
old.Content = val
err = c.UpdateDNSRecord(context.Background(), c.zoneID, old.ID, old)
updated++
record := cloudflare.UpdateDNSRecordParams{
Type: old.Type,
Name: old.Name,
Content: val,
Data: old.Data,
ID: old.ID,
Priority: old.Priority,
TTL: old.TTL,
Proxied: old.Proxied,
Tags: old.Tags,
}
_, err = c.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record)
} else {
skipped++
log.Debug(fmt.Sprintf("Skipping %s = %q", path, val))
}
if err != nil {
return fmt.Errorf("failed to publish %s: %v", path, err)
}
}
log.Info("Updated DNS entries", "new", created, "updated", updated, "untouched", skipped)
// Iterate over the old records and delete anything stale.
deleted := 0
log.Info("Deleting stale DNS entries")
for path, entry := range existing {
if _, ok := records[path]; ok {
continue
}
// Stale entry, nuke it.
log.Info(fmt.Sprintf("Deleting %s = %q", path, entry.Content))
if err := c.DeleteDNSRecord(context.Background(), c.zoneID, entry.ID); err != nil {
log.Debug(fmt.Sprintf("Deleting %s = %q", path, entry.Content))
deleted++
if err := c.DeleteDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), entry.ID); err != nil {
return fmt.Errorf("failed to delete %s: %v", path, err)
}
}
log.Info("Deleted stale DNS entries", "count", deleted)
return nil
}

View File

@@ -20,7 +20,6 @@ import (
"context"
"errors"
"fmt"
"sort"
"strconv"
"strings"
"time"
@@ -33,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
"github.com/urfave/cli/v2"
"golang.org/x/exp/slices"
)
const (
@@ -81,7 +81,7 @@ func newRoute53Client(ctx *cli.Context) *route53Client {
akey := ctx.String(route53AccessKeyFlag.Name)
asec := ctx.String(route53AccessSecretFlag.Name)
if akey == "" || asec == "" {
exit(fmt.Errorf("need Route53 Access Key ID and secret to proceed"))
exit(errors.New("need Route53 Access Key ID and secret to proceed"))
}
creds := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(akey, asec, ""))
cfg, err := config.LoadDefaultConfig(context.Background(), config.WithCredentialsProvider(creds))
@@ -221,7 +221,13 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e
}
records = lrecords
var changes []types.Change
var (
changes []types.Change
inserts int
upserts int
skips int
)
for path, newValue := range records {
prevRecords, exists := existing[path]
prevValue := strings.Join(prevRecords.values, "")
@@ -237,20 +243,30 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e
if !exists {
// Entry is unknown, push a new one
log.Info(fmt.Sprintf("Creating %s = %s", path, newValue))
log.Debug(fmt.Sprintf("Creating %s = %s", path, newValue))
changes = append(changes, newTXTChange("CREATE", path, ttl, newValue))
inserts++
} else if prevValue != newValue || prevRecords.ttl != ttl {
// Entry already exists, only change its content.
log.Info(fmt.Sprintf("Updating %s from %s to %s", path, prevValue, newValue))
changes = append(changes, newTXTChange("UPSERT", path, ttl, newValue))
upserts++
} else {
log.Debug(fmt.Sprintf("Skipping %s = %s", path, newValue))
skips++
}
}
// Iterate over the old records and delete anything stale.
changes = append(changes, makeDeletionChanges(existing, records)...)
deletions := makeDeletionChanges(existing, records)
changes = append(changes, deletions...)
log.Info("Computed DNS changes",
"changes", len(changes),
"inserts", inserts,
"skips", skips,
"deleted", len(deletions),
"upserts", upserts)
// Ensure changes are in the correct order.
sortChanges(changes)
return changes
@@ -263,7 +279,7 @@ func makeDeletionChanges(records map[string]recordSet, keep map[string]string) [
if _, ok := keep[path]; ok {
continue
}
log.Info(fmt.Sprintf("Deleting %s = %s", path, strings.Join(set.values, "")))
log.Debug(fmt.Sprintf("Deleting %s = %s", path, strings.Join(set.values, "")))
changes = append(changes, newTXTChange("DELETE", path, set.ttl, set.values...))
}
return changes
@@ -272,11 +288,17 @@ func makeDeletionChanges(records map[string]recordSet, keep map[string]string) [
// sortChanges ensures DNS changes are in leaf-added -> root-changed -> leaf-deleted order.
func sortChanges(changes []types.Change) {
score := map[string]int{"CREATE": 1, "UPSERT": 2, "DELETE": 3}
sort.Slice(changes, func(i, j int) bool {
if changes[i].Action == changes[j].Action {
return *changes[i].ResourceRecordSet.Name < *changes[j].ResourceRecordSet.Name
slices.SortFunc(changes, func(a, b types.Change) int {
if a.Action == b.Action {
return strings.Compare(*a.ResourceRecordSet.Name, *b.ResourceRecordSet.Name)
}
return score[string(changes[i].Action)] < score[string(changes[j].Action)]
if score[string(a.Action)] < score[string(b.Action)] {
return -1
}
if score[string(a.Action)] > score[string(b.Action)] {
return 1
}
return 0
})
}
@@ -329,8 +351,9 @@ func (c *route53Client) collectRecords(name string) (map[string]recordSet, error
var req route53.ListResourceRecordSetsInput
req.HostedZoneId = &c.zoneID
existing := make(map[string]recordSet)
log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID)
for page := 0; ; page++ {
log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page)
log.Debug("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page)
resp, err := c.api.ListResourceRecordSets(context.TODO(), &req)
if err != nil {
return existing, err
@@ -360,7 +383,7 @@ func (c *route53Client) collectRecords(name string) (map[string]recordSet, error
req.StartRecordName = resp.NextRecordName
req.StartRecordType = resp.NextRecordType
}
log.Info("Loaded existing TXT records", "name", name, "zone", c.zoneID, "records", len(existing))
return existing, nil
}

View File

@@ -26,6 +26,7 @@ import (
// This test checks that computeChanges/splitChanges create DNS changes in
// leaf-added -> root-changed -> leaf-deleted order.
func TestRoute53ChangeSort(t *testing.T) {
t.Parallel()
testTree0 := map[string]recordSet{
"2kfjogvxdqtxxugbh7gs7naaai.n": {ttl: 3333, values: []string{
`"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`,
@@ -164,6 +165,7 @@ func TestRoute53ChangeSort(t *testing.T) {
// This test checks that computeChanges compares the quoted value of the records correctly.
func TestRoute53NoChange(t *testing.T) {
t.Parallel()
// Existing record set.
testTree0 := map[string]recordSet{
"n": {ttl: rootTTL, values: []string{

Some files were not shown because too many files have changed in this diff Show More