From d6655cb4506bf2e838eed5199b84bfc63bf4515a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 5 May 2025 16:20:38 +0200 Subject: [PATCH 001/365] version: begin v1.15.12 release cycle --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index 4b0a7ebb81..51cf410cda 100644 --- a/version/version.go +++ b/version/version.go @@ -17,8 +17,8 @@ package version const ( - Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 11 // Patch version component of the current release - Meta = "stable" // Version metadata to append to the version string + Major = 1 // Major version component of the current release + Minor = 15 // Minor version component of the current release + Patch = 12 // Patch version component of the current release + Meta = "unstable" // Version metadata to append to the version string ) From 79e8870e34ff946fa372c3bfb11b3d6de84dce9b Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Tue, 6 May 2025 13:30:19 +1000 Subject: [PATCH 002/365] go.mod: update pebble to v1.1.5 to reduce clutter in go.sum (#31541) ``` go get github.com/cockroachdb/pebble@v1.1.5 go mod tidy ``` Co-authored-by: lightclient --- go.mod | 12 +- go.sum | 403 ++------------------------------------------------------- 2 files changed, 18 insertions(+), 397 deletions(-) diff --git a/go.mod b/go.mod index 9682685937..924f0d2642 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 github.com/cespare/cp v0.1.0 github.com/cloudflare/cloudflare-go v0.114.0 - github.com/cockroachdb/pebble v1.1.2 + github.com/cockroachdb/pebble v1.1.5 github.com/consensys/gnark-crypto v0.16.0 github.com/crate-crypto/go-eth-kzg v1.3.0 github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a @@ -120,7 +120,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect @@ -133,10 +133,10 @@ require ( github.com/pion/transport/v3 v3.0.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.0 // indirect - github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/client_golang v1.15.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 1ac65bc01d..5d35a7a0e1 100644 --- a/go.sum +++ b/go.sum @@ -1,36 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= @@ -43,8 +10,6 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -53,11 +18,6 @@ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDO github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA= @@ -86,30 +46,20 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 h1:0BkLfgeDjfZnZ+MhB3ONb01u9pwF github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ= github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8= github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.114.0 h1:ucoti4/7Exo0XQ+rzpn1H+IfVVe++zgiM+tyKtf0HUA= github.com/cloudflare/cloudflare-go v0.114.0/go.mod h1:O7fYfFfA6wKqKFn2QIR9lhj7FDw6VQCGOY6hd2TBtd0= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= @@ -118,8 +68,8 @@ github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/e github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= -github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= +github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= @@ -162,10 +112,6 @@ github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjU github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= @@ -191,15 +137,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -207,86 +144,44 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -294,8 +189,6 @@ github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY4 github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -306,7 +199,6 @@ github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= @@ -322,15 +214,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I= github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8= github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= @@ -342,9 +225,6 @@ github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -378,9 +258,8 @@ github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= @@ -390,13 +269,6 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= @@ -431,7 +303,6 @@ github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -439,29 +310,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= -github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= +github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/protolambda/bls12-381-util v0.1.0 h1:05DU2wJN7DTU7z28+Q+zejXkIsA/MF8JZQGhtBZZiWk= github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4= github.com/protolambda/zrnt v0.34.1 h1:qW55rnhZJDnOb3TwFiFRJZi3yTXFrJdGOFQM7vCwYGg= @@ -472,7 +328,6 @@ github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48 h github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= @@ -483,16 +338,11 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -518,24 +368,14 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -545,77 +385,24 @@ golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= @@ -623,78 +410,37 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -716,9 +462,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -730,54 +474,14 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= @@ -788,87 +492,16 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -877,10 +510,8 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -888,15 +519,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= From 51b34efebcf36c4fd083b13b78ec49eb081623b9 Mon Sep 17 00:00:00 2001 From: jwasinger Date: Tue, 6 May 2025 12:40:03 +0800 Subject: [PATCH 003/365] cmd/utils: don't allow network ID override if a preset network is specified (#31630) --- cmd/geth/consolecmd_test.go | 3 +-- cmd/utils/flags.go | 24 +++++++----------------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/cmd/geth/consolecmd_test.go b/cmd/geth/consolecmd_test.go index b8c2c498a6..ca8efb5f98 100644 --- a/cmd/geth/consolecmd_test.go +++ b/cmd/geth/consolecmd_test.go @@ -39,9 +39,8 @@ const ( // child g gets a temporary data directory. func runMinimalGeth(t *testing.T, args ...string) *testgeth { // --holesky to make the 'writing genesis to disk' faster (no accounts) - // --networkid=1337 to avoid cache bump // --syncmode=full to avoid allocating fast sync bloom - allArgs := []string{"--holesky", "--networkid", "1337", "--authrpc.port", "0", "--syncmode=full", "--port", "0", + allArgs := []string{"--holesky", "--authrpc.port", "0", "--syncmode=full", "--port", "0", "--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64", "--datadir.minfreedisk", "0"} return runGeth(t, append(allArgs, args...)...) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b26f43b376..44363d13f4 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1571,8 +1571,8 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) { // SetEthConfig applies eth-related command line flags to the config. func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { - // Avoid conflicting network flags - flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag) + // Avoid conflicting network flags, don't allow network id override on preset networks + flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag, NetworkIdFlag) flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer // Set configurations from CLI flags @@ -1743,33 +1743,23 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { // Override any default configs for hard coded networks. switch { case ctx.Bool(MainnetFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 1 - } + cfg.NetworkId = 1 cfg.Genesis = core.DefaultGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) case ctx.Bool(HoleskyFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 17000 - } + cfg.NetworkId = 17000 cfg.Genesis = core.DefaultHoleskyGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.HoleskyGenesisHash) case ctx.Bool(SepoliaFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 11155111 - } + cfg.NetworkId = 11155111 cfg.Genesis = core.DefaultSepoliaGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash) case ctx.Bool(HoodiFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 560048 - } + cfg.NetworkId = 560048 cfg.Genesis = core.DefaultHoodiGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.HoodiGenesisHash) case ctx.Bool(DeveloperFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 1337 - } + cfg.NetworkId = 1337 cfg.SyncMode = ethconfig.FullSync // Create new developer account or reuse existing one var ( From 3e356d69efcde2ce5f287863be5eb4f71177f607 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 7 May 2025 12:53:45 +0200 Subject: [PATCH 004/365] beacon/blsync: fix requests encoding in engine_newPayloadV4 (#31775) This fixes an issue where blocks containing CL requests triggered an error in the engine API. The encoding of requests used base64 instead of hex. --- beacon/blsync/engineclient.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/beacon/blsync/engineclient.go b/beacon/blsync/engineclient.go index 77bee83f5b..f9821fc6f3 100644 --- a/beacon/blsync/engineclient.go +++ b/beacon/blsync/engineclient.go @@ -26,6 +26,7 @@ import ( "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/hexutil" ctypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" @@ -104,7 +105,11 @@ func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent) method = "engine_newPayloadV4" parentBeaconRoot := event.BeaconHead.ParentRoot blobHashes := collectBlobHashes(event.Block) - params = append(params, blobHashes, parentBeaconRoot, event.ExecRequests) + hexRequests := make([]hexutil.Bytes, len(event.ExecRequests)) + for i := range event.ExecRequests { + hexRequests[i] = hexutil.Bytes(event.ExecRequests[i]) + } + params = append(params, blobHashes, parentBeaconRoot, hexRequests) case "deneb": method = "engine_newPayloadV3" parentBeaconRoot := event.BeaconHead.ParentRoot From 0d5de826da144cef795542a3489f899f49dee1e8 Mon Sep 17 00:00:00 2001 From: Csaba Kiraly Date: Wed, 7 May 2025 15:34:52 +0200 Subject: [PATCH 005/365] p2p: add metrics for inbound connection errors (#31652) Add metics detailing reasons we reject inbound connections for, and reasons these connections fail during the handshake. --- p2p/metrics.go | 42 ++++++++++++++++++++++++++++++++++++++++++ p2p/server.go | 2 ++ 2 files changed, 44 insertions(+) diff --git a/p2p/metrics.go b/p2p/metrics.go index 29c2acb0cb..c44a878aa4 100644 --- a/p2p/metrics.go +++ b/p2p/metrics.go @@ -66,6 +66,18 @@ var ( // capture the rest of errors that are not handled by the above meters dialOtherError = metrics.NewRegisteredMeter("p2p/dials/error/other", nil) + + // handshake error meters for inbound connections + serveTooManyPeers = metrics.NewRegisteredMeter("p2p/serves/error/saturated", nil) + serveAlreadyConnected = metrics.NewRegisteredMeter("p2p/serves/error/known", nil) + serveSelf = metrics.NewRegisteredMeter("p2p/serves/error/self", nil) + serveUselessPeer = metrics.NewRegisteredMeter("p2p/serves/error/useless", nil) + serveUnexpectedIdentity = metrics.NewRegisteredMeter("p2p/serves/error/id/unexpected", nil) + serveEncHandshakeError = metrics.NewRegisteredMeter("p2p/serves/error/rlpx/enc", nil) //EOF; connection reset during handshake; (message too big?) + serveProtoHandshakeError = metrics.NewRegisteredMeter("p2p/serves/error/rlpx/proto", nil) + + // capture the rest of errors that are not handled by the above meters + serveOtherError = metrics.NewRegisteredMeter("p2p/serves/error/other", nil) ) // markDialError matches errors that occur while setting up a dial connection to the @@ -99,6 +111,36 @@ func markDialError(err error) { } } +// markServeError matches errors that occur while serving an inbound connection +// to the corresponding meter. +func markServeError(err error) { + if !metrics.Enabled() { + return + } + + var reason DiscReason + var handshakeErr *protoHandshakeError + d := errors.As(err, &reason) + switch { + case d && reason == DiscTooManyPeers: + serveTooManyPeers.Mark(1) + case d && reason == DiscAlreadyConnected: + serveAlreadyConnected.Mark(1) + case d && reason == DiscSelf: + serveSelf.Mark(1) + case d && reason == DiscUselessPeer: + serveUselessPeer.Mark(1) + case d && reason == DiscUnexpectedIdentity: + serveUnexpectedIdentity.Mark(1) + case errors.As(err, &handshakeErr): + serveProtoHandshakeError.Mark(1) + case errors.Is(err, errEncHandshakeError): + serveEncHandshakeError.Mark(1) + default: + serveOtherError.Mark(1) + } +} + // meteredConn is a wrapper around a net.Conn that meters both the // inbound and outbound network traffic. type meteredConn struct { diff --git a/p2p/server.go b/p2p/server.go index d9105976dd..f3a58bba29 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -864,6 +864,8 @@ func (srv *Server) SetupConn(fd net.Conn, flags connFlag, dialDest *enode.Node) if err != nil { if !c.is(inboundConn) { markDialError(err) + } else { + markServeError(err) } c.close(err) } From 07d073bc5a711ddf40f25c56b54f88badf3c3694 Mon Sep 17 00:00:00 2001 From: JukLee0ira Date: Thu, 8 May 2025 14:57:17 +0800 Subject: [PATCH 006/365] internal/web3ext: remove the legacy backtraceAt method (#31783) The function `BacktraceAt` has been removed in #28187 . But the API end-point `debug_backtraceAt` is not removed from the file `internal/web3ext/web3ext.go`. --- internal/web3ext/web3ext.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index aed6bbbdb9..a6d93fc1c5 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -247,11 +247,6 @@ web3._extend({ call: 'debug_vmodule', params: 1 }), - new web3._extend.Method({ - name: 'backtraceAt', - call: 'debug_backtraceAt', - params: 1, - }), new web3._extend.Method({ name: 'stacks', call: 'debug_stacks', From 10519768a2f7259e55cc34e51ff6ec73e6a703e9 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Thu, 8 May 2025 19:10:26 +0800 Subject: [PATCH 007/365] core, ethdb: introduce database sync function (#31703) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request introduces a SyncKeyValue function to the ethdb.KeyValueStore interface, providing the ability to forcibly flush all previous writes to disk. This functionality is critical for go-ethereum, which internally uses two independent database engines: a key-value store (such as Pebble, LevelDB, or memoryDB for testing) and a flat-file–based freezer. To ensure write-order consistency between these engines, the key-value store must be explicitly synced before writing to the freezer and vice versa. Fixes - https://github.com/ethereum/go-ethereum/issues/31405 - https://github.com/ethereum/go-ethereum/issues/29819 --- core/bench_test.go | 8 +++---- core/blockchain.go | 24 ++++++++++---------- core/blockchain_repair_test.go | 8 +++---- core/blockchain_sethead_test.go | 2 +- core/blockchain_snapshot_test.go | 4 ++-- core/blockchain_test.go | 2 +- core/headerchain.go | 35 +++++++++++++++++++++++++++- core/rawdb/chain_freezer.go | 2 +- core/rawdb/database.go | 4 ++-- core/rawdb/freezer.go | 4 ++-- core/rawdb/freezer_memory.go | 4 ++-- core/rawdb/freezer_resettable.go | 6 ++--- core/rawdb/freezer_test.go | 2 +- core/rawdb/table.go | 12 +++++++--- ethdb/database.go | 14 +++++++++--- ethdb/leveldb/leveldb.go | 16 +++++++++++++ ethdb/memorydb/memorydb.go | 6 +++++ ethdb/pebble/pebble.go | 39 ++++++++++++++++++++++++++++---- ethdb/pebble/pebble_test.go | 24 ++++++++++++++++++++ ethdb/remotedb/remotedb.go | 6 ++++- node/database.go | 13 ++++------- trie/trie_test.go | 1 + triedb/pathdb/buffer.go | 9 +++++--- triedb/pathdb/database.go | 9 ++++++++ 24 files changed, 194 insertions(+), 60 deletions(-) diff --git a/core/bench_test.go b/core/bench_test.go index 00f924076a..155fa6c3b5 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -183,7 +183,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { if !disk { db = rawdb.NewMemoryDatabase() } else { - pdb, err := pebble.New(b.TempDir(), 128, 128, "", false, true) + pdb, err := pebble.New(b.TempDir(), 128, 128, "", false) if err != nil { b.Fatalf("cannot create temporary database: %v", err) } @@ -303,7 +303,7 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin func benchWriteChain(b *testing.B, full bool, count uint64) { genesis := &Genesis{Config: params.AllEthashProtocolChanges} for i := 0; i < b.N; i++ { - pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false, true) + pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false) if err != nil { b.Fatalf("error opening database: %v", err) } @@ -316,7 +316,7 @@ func benchWriteChain(b *testing.B, full bool, count uint64) { func benchReadChain(b *testing.B, full bool, count uint64) { dir := b.TempDir() - pdb, err := pebble.New(dir, 1024, 128, "", false, true) + pdb, err := pebble.New(dir, 1024, 128, "", false) if err != nil { b.Fatalf("error opening database: %v", err) } @@ -332,7 +332,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) { b.ResetTimer() for i := 0; i < b.N; i++ { - pdb, err = pebble.New(dir, 1024, 128, "", false, true) + pdb, err = pebble.New(dir, 1024, 128, "", false) if err != nil { b.Fatalf("error opening database: %v", err) } diff --git a/core/blockchain.go b/core/blockchain.go index 6667f64911..b0c1b119fc 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -979,17 +979,16 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha // Ignore the error here since light client won't hit this path frozen, _ := bc.db.Ancients() if num+1 <= frozen { - // Truncate all relative data(header, total difficulty, body, receipt - // and canonical hash) from ancient store. - if _, err := bc.db.TruncateHead(num); err != nil { - log.Crit("Failed to truncate ancient data", "number", num, "err", err) - } - // Remove the hash <-> number mapping from the active store. - rawdb.DeleteHeaderNumber(db, hash) + // The chain segment, such as the block header, canonical hash, + // body, and receipt, will be removed from the ancient store + // in one go. + // + // The hash-to-number mapping in the key-value store will be + // removed by the hc.SetHead function. } else { - // Remove relative body and receipts from the active store. - // The header, total difficulty and canonical hash will be - // removed in the hc.SetHead function. + // Remove the associated body and receipts from the key-value store. + // The header, hash-to-number mapping, and canonical hash will be + // removed by the hc.SetHead function. rawdb.DeleteBody(db, hash, num) rawdb.DeleteReceipts(db, hash, num) } @@ -1361,7 +1360,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ size += writeSize // Sync the ancient store explicitly to ensure all data has been flushed to disk. - if err := bc.db.Sync(); err != nil { + if err := bc.db.SyncAncient(); err != nil { return 0, err } // Write hash to number mappings @@ -2627,7 +2626,8 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e if err != nil { return 0, err } - if err := bc.db.Sync(); err != nil { + // Sync the ancient store explicitly to ensure all data has been flushed to disk. + if err := bc.db.SyncAncient(); err != nil { return 0, err } // Write hash to number mappings diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 3ff1d77fc8..6c52d057ad 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -1765,7 +1765,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false, true) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } @@ -1850,7 +1850,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s chain.stopWithoutSaving() // Start a new blockchain back up and see where the repair leads us - pdb, err = pebble.New(datadir, 0, 0, "", false, true) + pdb, err = pebble.New(datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to reopen persistent key-value database: %v", err) } @@ -1915,7 +1915,7 @@ func testIssue23496(t *testing.T, scheme string) { datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false, true) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } @@ -1973,7 +1973,7 @@ func testIssue23496(t *testing.T, scheme string) { chain.stopWithoutSaving() // Start a new blockchain back up and see where the repair leads us - pdb, err = pebble.New(datadir, 0, 0, "", false, true) + pdb, err = pebble.New(datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to reopen persistent key-value database: %v", err) } diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index e998b510df..424854b2bf 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -1969,7 +1969,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false, true) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index 23effea15e..1a6fe38af6 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -66,7 +66,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false, true) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } @@ -257,7 +257,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) { chain.triedb.Close() // Start a new blockchain back up and see where the repair leads us - pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false, true) + pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 134deee237..b981c33f21 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -2492,7 +2492,7 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) { datadir := t.TempDir() ancient := path.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false, true) + pdb, err := pebble.New(datadir, 0, 0, "", false) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } diff --git a/core/headerchain.go b/core/headerchain.go index f7acc49bef..6e70dfa865 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -591,17 +591,50 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat hashes = append(hashes, hdr.Hash()) } for _, hash := range hashes { + // Remove the associated block body and receipts if required. + // + // If the block is in the chain freezer, then this delete operation + // is actually ineffective. if delFn != nil { delFn(batch, hash, num) } + // Remove the hash->number mapping along with the header itself rawdb.DeleteHeader(batch, hash, num) } + // Remove the number->hash mapping rawdb.DeleteCanonicalHash(batch, num) } } // Flush all accumulated deletions. if err := batch.Write(); err != nil { - log.Crit("Failed to rewind block", "error", err) + log.Crit("Failed to commit batch in setHead", "err", err) + } + // Explicitly flush the pending writes in the key-value store to disk, ensuring + // data durability of the previous deletions. + if err := hc.chainDb.SyncKeyValue(); err != nil { + log.Crit("Failed to sync the key-value store in setHead", "err", err) + } + // Truncate the excessive chain segments in the ancient store. + // These are actually deferred deletions from the loop above. + // + // This step must be performed after synchronizing the key-value store; + // otherwise, in the event of a panic, it's theoretically possible to + // lose recent key-value store writes while the ancient store deletions + // remain, leading to data inconsistency, e.g., the gap between the key + // value store and ancient can be created due to unclean shutdown. + if delFn != nil { + // Ignore the error here since light client won't hit this path + frozen, _ := hc.chainDb.Ancients() + header := hc.CurrentHeader() + + // Truncate the excessive chain segment above the current chain head + // in the ancient store. + if header.Number.Uint64()+1 < frozen { + _, err := hc.chainDb.TruncateHead(header.Number.Uint64() + 1) + if err != nil { + log.Crit("Failed to truncate head block", "err", err) + } + } } // Clear out any stale content from the caches hc.headerCache.Purge() diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go index f3c671f45a..cc7a62df32 100644 --- a/core/rawdb/chain_freezer.go +++ b/core/rawdb/chain_freezer.go @@ -205,7 +205,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) { continue } // Batch of blocks have been frozen, flush them before wiping from key-value store - if err := f.Sync(); err != nil { + if err := f.SyncAncient(); err != nil { log.Crit("Failed to flush frozen tables", "err", err) } // Wipe out all data from the active database diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 2a50e3f9ee..a03dbafb1f 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -131,8 +131,8 @@ func (db *nofreezedb) TruncateTail(items uint64) (uint64, error) { return 0, errNotSupported } -// Sync returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Sync() error { +// SyncAncient returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) SyncAncient() error { return errNotSupported } diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 105d3af934..1e5b98c7fe 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -325,8 +325,8 @@ func (f *Freezer) TruncateTail(tail uint64) (uint64, error) { return old, nil } -// Sync flushes all data tables to disk. -func (f *Freezer) Sync() error { +// SyncAncient flushes all data tables to disk. +func (f *Freezer) SyncAncient() error { var errs []error for _, table := range f.tables { if err := table.Sync(); err != nil { diff --git a/core/rawdb/freezer_memory.go b/core/rawdb/freezer_memory.go index 4274546de5..bd286f45f5 100644 --- a/core/rawdb/freezer_memory.go +++ b/core/rawdb/freezer_memory.go @@ -395,8 +395,8 @@ func (f *MemoryFreezer) TruncateTail(tail uint64) (uint64, error) { return old, nil } -// Sync flushes all data tables to disk. -func (f *MemoryFreezer) Sync() error { +// SyncAncient flushes all data tables to disk. +func (f *MemoryFreezer) SyncAncient() error { return nil } diff --git a/core/rawdb/freezer_resettable.go b/core/rawdb/freezer_resettable.go index 2e64e6074c..01df2877d9 100644 --- a/core/rawdb/freezer_resettable.go +++ b/core/rawdb/freezer_resettable.go @@ -194,12 +194,12 @@ func (f *resettableFreezer) TruncateTail(tail uint64) (uint64, error) { return f.freezer.TruncateTail(tail) } -// Sync flushes all data tables to disk. -func (f *resettableFreezer) Sync() error { +// SyncAncient flushes all data tables to disk. +func (f *resettableFreezer) SyncAncient() error { f.lock.RLock() defer f.lock.RUnlock() - return f.freezer.Sync() + return f.freezer.SyncAncient() } // AncientDatadir returns the path of the ancient store. diff --git a/core/rawdb/freezer_test.go b/core/rawdb/freezer_test.go index 150734d3ac..a7a3559ec4 100644 --- a/core/rawdb/freezer_test.go +++ b/core/rawdb/freezer_test.go @@ -392,7 +392,7 @@ func TestFreezerCloseSync(t *testing.T) { if err := f.Close(); err != nil { t.Fatal(err) } - if err := f.Sync(); err == nil { + if err := f.SyncAncient(); err == nil { t.Fatalf("want error, have nil") } else if have, want := err.Error(), "[closed closed]"; have != want { t.Fatalf("want %v, have %v", have, want) diff --git a/core/rawdb/table.go b/core/rawdb/table.go index 1a9060b636..9a342a8217 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -107,10 +107,10 @@ func (t *table) TruncateTail(items uint64) (uint64, error) { return t.db.TruncateTail(items) } -// Sync is a noop passthrough that just forwards the request to the underlying +// SyncAncient is a noop passthrough that just forwards the request to the underlying // database. -func (t *table) Sync() error { - return t.db.Sync() +func (t *table) SyncAncient() error { + return t.db.SyncAncient() } // AncientDatadir returns the ancient datadir of the underlying database. @@ -188,6 +188,12 @@ func (t *table) Compact(start []byte, limit []byte) error { return t.db.Compact(start, limit) } +// SyncKeyValue ensures that all pending writes are flushed to disk, +// guaranteeing data durability up to the point. +func (t *table) SyncKeyValue() error { + return t.db.SyncKeyValue() +} + // NewBatch creates a write-only database that buffers changes to its host db // until a final write is called, each operation prefixing all keys with the // pre-configured string. diff --git a/ethdb/database.go b/ethdb/database.go index f2d458b85f..7f421752c4 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -57,6 +57,13 @@ type KeyValueStater interface { Stat() (string, error) } +// KeyValueSyncer wraps the SyncKeyValue method of a backing data store. +type KeyValueSyncer interface { + // SyncKeyValue ensures that all pending writes are flushed to disk, + // guaranteeing data durability up to the point. + SyncKeyValue() error +} + // Compacter wraps the Compact method of a backing data store. type Compacter interface { // Compact flattens the underlying data store for the given key range. In essence, @@ -75,6 +82,7 @@ type KeyValueStore interface { KeyValueReader KeyValueWriter KeyValueStater + KeyValueSyncer KeyValueRangeDeleter Batcher Iteratee @@ -126,6 +134,9 @@ type AncientWriter interface { // The integer return value is the total size of the written data. ModifyAncients(func(AncientWriteOp) error) (int64, error) + // SyncAncient flushes all in-memory ancient store data to disk. + SyncAncient() error + // TruncateHead discards all but the first n ancient data from the ancient store. // After the truncation, the latest item can be accessed it item_n-1(start from 0). TruncateHead(n uint64) (uint64, error) @@ -138,9 +149,6 @@ type AncientWriter interface { // // Note that data marked as non-prunable will still be retained and remain accessible. TruncateTail(n uint64) (uint64, error) - - // Sync flushes all in-memory ancient store data to disk. - Sync() error } // AncientWriteOp is given to the function argument of ModifyAncients. diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go index ef02e91822..223d01aff6 100644 --- a/ethdb/leveldb/leveldb.go +++ b/ethdb/leveldb/leveldb.go @@ -324,6 +324,22 @@ func (db *Database) Path() string { return db.fn } +// SyncKeyValue flushes all pending writes in the write-ahead-log to disk, +// ensuring data durability up to that point. +func (db *Database) SyncKeyValue() error { + // In theory, the WAL (Write-Ahead Log) can be explicitly synchronized using + // a write operation with SYNC=true. However, there is no dedicated key reserved + // for this purpose, and even a nil key (key=nil) is considered a valid + // database entry. + // + // In LevelDB, writes are blocked until the data is written to the WAL, meaning + // recent writes won't be lost unless a power failure or system crash occurs. + // Additionally, LevelDB is no longer the default database engine and is likely + // only used by hash-mode archive nodes. Given this, the durability guarantees + // without explicit sync are acceptable in the context of LevelDB. + return nil +} + // meter periodically retrieves internal leveldb counters and reports them to // the metrics subsystem. func (db *Database) meter(refresh time.Duration, namespace string) { diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go index a797275e92..f56727cf4a 100644 --- a/ethdb/memorydb/memorydb.go +++ b/ethdb/memorydb/memorydb.go @@ -199,6 +199,12 @@ func (db *Database) Compact(start []byte, limit []byte) error { return nil } +// SyncKeyValue ensures that all pending writes are flushed to disk, +// guaranteeing data durability up to the point. +func (db *Database) SyncKeyValue() error { + return nil +} + // Len returns the number of entries currently present in the memory database. // // Note, this method is only used for testing (i.e. not public in general) and diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index 969e67af5a..9ece995655 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -144,7 +144,7 @@ func (l panicLogger) Fatalf(format string, args ...interface{}) { // New returns a wrapped pebble DB object. The namespace is the prefix that the // metrics reporting should use for surfacing internal stats. -func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (*Database, error) { +func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) { // Ensure we have some minimal caching and file guarantees if cache < minCache { cache = minCache @@ -182,10 +182,18 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e memTableSize = maxMemTableSize - 1 } db := &Database{ - fn: file, - log: logger, - quitChan: make(chan chan error), - writeOptions: &pebble.WriteOptions{Sync: !ephemeral}, + fn: file, + log: logger, + quitChan: make(chan chan error), + + // Use asynchronous write mode by default. Otherwise, the overhead of frequent fsync + // operations can be significant, especially on platforms with slow fsync performance + // (e.g., macOS) or less capable SSDs. + // + // Note that enabling async writes means recent data may be lost in the event of an + // application-level panic (writes will also be lost on a machine-level failure, + // of course). Geth is expected to handle recovery from an unclean shutdown. + writeOptions: pebble.NoSync, } opt := &pebble.Options{ // Pebble has a single combined cache area and the write @@ -228,6 +236,15 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e WriteStallEnd: db.onWriteStallEnd, }, Logger: panicLogger{}, // TODO(karalabe): Delete when this is upstreamed in Pebble + + // Pebble is configured to use asynchronous write mode, meaning write operations + // return as soon as the data is cached in memory, without waiting for the WAL + // to be written. This mode offers better write performance but risks losing + // recent writes if the application crashes or a power failure/system crash occurs. + // + // By setting the WALBytesPerSync, the cached WAL writes will be periodically + // flushed at the background if the accumulated size exceeds this threshold. + WALBytesPerSync: 5 * ethdb.IdealBatchSize, } // Disable seek compaction explicitly. Check https://github.com/ethereum/go-ethereum/pull/20130 // for more details. @@ -414,6 +431,18 @@ func (d *Database) Path() string { return d.fn } +// SyncKeyValue flushes all pending writes in the write-ahead-log to disk, +// ensuring data durability up to that point. +func (d *Database) SyncKeyValue() error { + // The entry (value=nil) is not written to the database; it is only + // added to the WAL. Writing this special log entry in sync mode + // automatically flushes all previous writes, ensuring database + // durability up to this point. + b := d.db.NewBatch() + b.LogData(nil, nil) + return d.db.Apply(b, pebble.Sync) +} + // meter periodically retrieves internal pebble counters and reports them to // the metrics subsystem. func (d *Database) meter(refresh time.Duration, namespace string) { diff --git a/ethdb/pebble/pebble_test.go b/ethdb/pebble/pebble_test.go index 3265491d4a..e703a8d0ce 100644 --- a/ethdb/pebble/pebble_test.go +++ b/ethdb/pebble/pebble_test.go @@ -17,6 +17,7 @@ package pebble import ( + "errors" "testing" "github.com/cockroachdb/pebble" @@ -54,3 +55,26 @@ func BenchmarkPebbleDB(b *testing.B) { } }) } + +func TestPebbleLogData(t *testing.T) { + db, err := pebble.Open("", &pebble.Options{ + FS: vfs.NewMem(), + }) + if err != nil { + t.Fatal(err) + } + + _, _, err = db.Get(nil) + if !errors.Is(err, pebble.ErrNotFound) { + t.Fatal("Unknown database entry") + } + + b := db.NewBatch() + b.LogData(nil, nil) + db.Apply(b, pebble.Sync) + + _, _, err = db.Get(nil) + if !errors.Is(err, pebble.ErrNotFound) { + t.Fatal("Unknown database entry") + } +} diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go index 8a91fdbcf2..a417a25854 100644 --- a/ethdb/remotedb/remotedb.go +++ b/ethdb/remotedb/remotedb.go @@ -110,7 +110,7 @@ func (db *Database) TruncateTail(n uint64) (uint64, error) { panic("not supported") } -func (db *Database) Sync() error { +func (db *Database) SyncAncient() error { return nil } @@ -138,6 +138,10 @@ func (db *Database) Compact(start []byte, limit []byte) error { return nil } +func (db *Database) SyncKeyValue() error { + return nil +} + func (db *Database) Close() error { db.remote.Close() return nil diff --git a/node/database.go b/node/database.go index b7d0d856cb..e3ccb91066 100644 --- a/node/database.go +++ b/node/database.go @@ -36,11 +36,6 @@ type openOptions struct { Cache int // the capacity(in megabytes) of the data caching Handles int // number of files to be open simultaneously ReadOnly bool - - // Ephemeral means that filesystem sync operations should be avoided: - // data integrity in the face of a crash is not important. This option - // should typically be used in tests. - Ephemeral bool } // openDatabase opens both a disk-based key-value database such as leveldb or pebble, but also @@ -83,7 +78,7 @@ func openKeyValueDatabase(o openOptions) (ethdb.Database, error) { } if o.Type == rawdb.DBPebble || existingDb == rawdb.DBPebble { log.Info("Using pebble as the backing database") - return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) + return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) } if o.Type == rawdb.DBLeveldb || existingDb == rawdb.DBLeveldb { log.Info("Using leveldb as the backing database") @@ -91,7 +86,7 @@ func openKeyValueDatabase(o openOptions) (ethdb.Database, error) { } // No pre-existing database, no user-requested one either. Default to Pebble. log.Info("Defaulting to pebble as the backing database") - return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) + return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) } // newLevelDBDatabase creates a persistent key-value database without a freezer @@ -107,8 +102,8 @@ func newLevelDBDatabase(file string, cache int, handles int, namespace string, r // newPebbleDBDatabase creates a persistent key-value database without a freezer // moving immutable chain segments into cold storage. -func newPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (ethdb.Database, error) { - db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral) +func newPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { + db, err := pebble.New(file, cache, handles, namespace, readonly) if err != nil { return nil, err } diff --git a/trie/trie_test.go b/trie/trie_test.go index 54d1b083d8..91fde6dbf2 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -830,6 +830,7 @@ func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBat func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} } func (s *spongeDb) Stat() (string, error) { panic("implement me") } func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") } +func (s *spongeDb) SyncKeyValue() error { return nil } func (s *spongeDb) Close() error { return nil } func (s *spongeDb) Put(key []byte, value []byte) error { var ( diff --git a/triedb/pathdb/buffer.go b/triedb/pathdb/buffer.go index dea8875bda..c4e081b973 100644 --- a/triedb/pathdb/buffer.go +++ b/triedb/pathdb/buffer.go @@ -135,10 +135,13 @@ func (b *buffer) flush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, node start = time.Now() batch = db.NewBatchWithSize(b.nodes.dbsize() * 11 / 10) // extra 10% for potential pebble internal stuff ) - // Explicitly sync the state freezer, ensuring that all written - // data is transferred to disk before updating the key-value store. + // Explicitly sync the state freezer to ensure all written data is persisted to disk + // before updating the key-value store. + // + // This step is crucial to guarantee that the corresponding state history remains + // available for state rollback. if freezer != nil { - if err := freezer.Sync(); err != nil { + if err := freezer.SyncAncient(); err != nil { return err } } diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index d48850c102..155e28543d 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -454,6 +454,15 @@ func (db *Database) Recover(root common.Hash) error { db.tree.reset(dl) } rawdb.DeleteTrieJournal(db.diskdb) + + // Explicitly sync the key-value store to ensure all recent writes are + // flushed to disk. This step is crucial to prevent a scenario where + // recent key-value writes are lost due to an application panic, while + // the associated state histories have already been removed, resulting + // in the inability to perform a state rollback. + if err := db.diskdb.SyncKeyValue(); err != nil { + return err + } _, err := truncateFromHead(db.diskdb, db.freezer, dl.stateID()) if err != nil { return err From 181dd2e66025ee6e5cd1c304f4c5f62f911d6272 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Thu, 8 May 2025 21:15:36 +0800 Subject: [PATCH 008/365] cmd/geth, internal: fix flaky console tests (#31784) This pull request bumps the timeout for flaky console tests on appveyor. --- cmd/geth/consolecmd_test.go | 6 +++--- eth/api_backend_test.go | 18 +++++++++++------- internal/cmdtest/test_cmd.go | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/cmd/geth/consolecmd_test.go b/cmd/geth/consolecmd_test.go index ca8efb5f98..4e1f6340a0 100644 --- a/cmd/geth/consolecmd_test.go +++ b/cmd/geth/consolecmd_test.go @@ -102,17 +102,17 @@ func TestAttachWelcome(t *testing.T) { "--http", "--http.port", httpPort, "--ws", "--ws.port", wsPort) t.Run("ipc", func(t *testing.T) { - waitForEndpoint(t, ipc, 4*time.Second) + waitForEndpoint(t, ipc, 2*time.Minute) testAttachWelcome(t, geth, "ipc:"+ipc, ipcAPIs) }) t.Run("http", func(t *testing.T) { endpoint := "http://127.0.0.1:" + httpPort - waitForEndpoint(t, endpoint, 4*time.Second) + waitForEndpoint(t, endpoint, 2*time.Minute) testAttachWelcome(t, geth, endpoint, httpAPIs) }) t.Run("ws", func(t *testing.T) { endpoint := "ws://127.0.0.1:" + wsPort - waitForEndpoint(t, endpoint, 4*time.Second) + waitForEndpoint(t, endpoint, 2*time.Minute) testAttachWelcome(t, geth, endpoint, httpAPIs) }) geth.Kill() diff --git a/eth/api_backend_test.go b/eth/api_backend_test.go index 049f68d827..dfca24aba7 100644 --- a/eth/api_backend_test.go +++ b/eth/api_backend_test.go @@ -134,13 +134,17 @@ func TestSendTx(t *testing.T) { func testSendTx(t *testing.T, withLocal bool) { b := initBackend(withLocal) - txA := pricedSetCodeTx(0, 250000, uint256.NewInt(params.GWei), uint256.NewInt(params.GWei), key, []unsignedAuth{ - { - nonce: 0, - key: key, - }, - }) - b.SendTx(context.Background(), txA) + txA := pricedSetCodeTx(0, 250000, uint256.NewInt(params.GWei), uint256.NewInt(params.GWei), key, []unsignedAuth{{nonce: 0, key: key}}) + if err := b.SendTx(context.Background(), txA); err != nil { + t.Fatalf("Failed to submit tx: %v", err) + } + for { + pending, _ := b.TxPool().ContentFrom(address) + if len(pending) == 1 { + break + } + time.Sleep(100 * time.Millisecond) + } txB := makeTx(1, nil, nil, key) err := b.SendTx(context.Background(), txB) diff --git a/internal/cmdtest/test_cmd.go b/internal/cmdtest/test_cmd.go index 4890d0b7c6..f6f0425598 100644 --- a/internal/cmdtest/test_cmd.go +++ b/internal/cmdtest/test_cmd.go @@ -237,7 +237,7 @@ func (tt *TestCmd) Kill() { } func (tt *TestCmd) withKillTimeout(fn func()) { - timeout := time.AfterFunc(30*time.Second, func() { + timeout := time.AfterFunc(2*time.Minute, func() { tt.Log("killing the child process (timeout)") tt.Kill() }) From 6bc57579d14063c0f2a9c7da5022d25b3a850cf3 Mon Sep 17 00:00:00 2001 From: maskpp Date: Thu, 8 May 2025 21:21:48 +0800 Subject: [PATCH 009/365] core/types: delete unused test variable (#31776) Delete the unused `Account.PrivateKey` variable. --- core/types/account.go | 12 ++++-------- core/types/gen_account.go | 22 ++++++++-------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/core/types/account.go b/core/types/account.go index 52ce184cda..bcfb83418c 100644 --- a/core/types/account.go +++ b/core/types/account.go @@ -38,17 +38,13 @@ type Account struct { Storage map[common.Hash]common.Hash `json:"storage,omitempty"` Balance *big.Int `json:"balance" gencodec:"required"` Nonce uint64 `json:"nonce,omitempty"` - - // used in tests - PrivateKey []byte `json:"secretKey,omitempty"` } type accountMarshaling struct { - Code hexutil.Bytes - Balance *math.HexOrDecimal256 - Nonce math.HexOrDecimal64 - Storage map[storageJSON]storageJSON - PrivateKey hexutil.Bytes + Code hexutil.Bytes + Balance *math.HexOrDecimal256 + Nonce math.HexOrDecimal64 + Storage map[storageJSON]storageJSON } // storageJSON represents a 256 bit byte array, but allows less than 256 bits when diff --git a/core/types/gen_account.go b/core/types/gen_account.go index 4e475896a7..89165ee3ad 100644 --- a/core/types/gen_account.go +++ b/core/types/gen_account.go @@ -17,11 +17,10 @@ var _ = (*accountMarshaling)(nil) // MarshalJSON marshals as JSON. func (a Account) MarshalJSON() ([]byte, error) { type Account struct { - Code hexutil.Bytes `json:"code,omitempty"` - Storage map[storageJSON]storageJSON `json:"storage,omitempty"` - Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` - Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` - PrivateKey hexutil.Bytes `json:"secretKey,omitempty"` + Code hexutil.Bytes `json:"code,omitempty"` + Storage map[storageJSON]storageJSON `json:"storage,omitempty"` + Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` + Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` } var enc Account enc.Code = a.Code @@ -33,18 +32,16 @@ func (a Account) MarshalJSON() ([]byte, error) { } enc.Balance = (*math.HexOrDecimal256)(a.Balance) enc.Nonce = math.HexOrDecimal64(a.Nonce) - enc.PrivateKey = a.PrivateKey return json.Marshal(&enc) } // UnmarshalJSON unmarshals from JSON. func (a *Account) UnmarshalJSON(input []byte) error { type Account struct { - Code *hexutil.Bytes `json:"code,omitempty"` - Storage map[storageJSON]storageJSON `json:"storage,omitempty"` - Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` - Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"` - PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"` + Code *hexutil.Bytes `json:"code,omitempty"` + Storage map[storageJSON]storageJSON `json:"storage,omitempty"` + Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` + Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"` } var dec Account if err := json.Unmarshal(input, &dec); err != nil { @@ -66,8 +63,5 @@ func (a *Account) UnmarshalJSON(input []byte) error { if dec.Nonce != nil { a.Nonce = uint64(*dec.Nonce) } - if dec.PrivateKey != nil { - a.PrivateKey = *dec.PrivateKey - } return nil } From 0f48cbf017d6ee721ec2b74fced95b05c155f72b Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Thu, 8 May 2025 22:27:01 +0800 Subject: [PATCH 010/365] core, triedb/pathdb: bail out error if write state history fails (#31781) This PR fixes an issue that could lead to data corruption. Writing the state history may fail due to insufficient disk space or other potential errors. With this change, the entire state insertion will be aborted instead of silently ignoring the error. Without this fix, state transitions would continue while the associated state history is lost. After a restart, the resulting gap would be detected, making recovery impossible. --- core/rawdb/accessors_state.go | 24 ++++++++++++++++-------- triedb/pathdb/disklayer.go | 2 ++ triedb/pathdb/history.go | 5 +++-- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/core/rawdb/accessors_state.go b/core/rawdb/accessors_state.go index adc77fae83..41e15debe9 100644 --- a/core/rawdb/accessors_state.go +++ b/core/rawdb/accessors_state.go @@ -258,13 +258,21 @@ func ReadStateHistory(db ethdb.AncientReaderOp, id uint64) ([]byte, []byte, []by // WriteStateHistory writes the provided state history to database. Compute the // position of state history in freezer by minus one since the id of first state // history starts from one(zero for initial state). -func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) { - db.ModifyAncients(func(op ethdb.AncientWriteOp) error { - op.AppendRaw(stateHistoryMeta, id-1, meta) - op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex) - op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex) - op.AppendRaw(stateHistoryAccountData, id-1, accounts) - op.AppendRaw(stateHistoryStorageData, id-1, storages) - return nil +func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) error { + _, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error { + if err := op.AppendRaw(stateHistoryMeta, id-1, meta); err != nil { + return err + } + if err := op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex); err != nil { + return err + } + if err := op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex); err != nil { + return err + } + if err := op.AppendRaw(stateHistoryAccountData, id-1, accounts); err != nil { + return err + } + return op.AppendRaw(stateHistoryStorageData, id-1, storages) }) + return err } diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index 184f6430a2..f3a60a507d 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -231,6 +231,8 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { oldest uint64 ) if dl.db.freezer != nil { + // Bail out with an error if writing the state history fails. + // This can happen, for example, if the device is full. err := writeHistory(dl.db.freezer, bottom) if err != nil { return nil, err diff --git a/triedb/pathdb/history.go b/triedb/pathdb/history.go index c063e45371..aed0296da5 100644 --- a/triedb/pathdb/history.go +++ b/triedb/pathdb/history.go @@ -542,8 +542,9 @@ func writeHistory(writer ethdb.AncientWriter, dl *diffLayer) error { indexSize := common.StorageSize(len(accountIndex) + len(storageIndex)) // Write history data into five freezer table respectively. - rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData) - + if err := rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData); err != nil { + return err + } historyDataBytesMeter.Mark(int64(dataSize)) historyIndexBytesMeter.Mark(int64(indexSize)) historyBuildTimeMeter.UpdateSince(start) From 485ff4bbff83abbf27a82a5660545e713c992c3f Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Thu, 8 May 2025 22:28:16 +0800 Subject: [PATCH 011/365] core: implement in-block prefetcher (#31557) This pull request enhances the block prefetcher by executing transactions in parallel to warm the cache alongside the main block processor. Unlike the original prefetcher, which only executes the next block and is limited to chain syncing, the new implementation can be applied to any block. This makes it useful not only during chain sync but also for regular block insertion after the initial sync. --------- Co-authored-by: Marius van der Wijden --- core/blockchain.go | 145 ++++++++++++++++-------------- core/blockchain_insert.go | 1 + core/state/database.go | 13 ++- core/state/reader.go | 180 ++++++++++++++++++++++++++++++++++---- core/state/statedb.go | 19 +++- core/state_prefetcher.go | 111 ++++++++++++++++------- core/state_transition.go | 4 +- triedb/pathdb/metrics.go | 4 +- 8 files changed, 351 insertions(+), 126 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index b0c1b119fc..3c691600eb 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -92,8 +92,10 @@ var ( blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil) blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil) - blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil) - blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil) + blockPrefetchExecuteTimer = metrics.NewRegisteredResettingTimer("chain/prefetch/executes", nil) + blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil) + blockPrefetchTxsInvalidMeter = metrics.NewRegisteredMeter("chain/prefetch/txs/invalid", nil) + blockPrefetchTxsValidMeter = metrics.NewRegisteredMeter("chain/prefetch/txs/valid", nil) errInsertionInterrupted = errors.New("insertion is interrupted") errChainStopped = errors.New("blockchain is stopped") @@ -1758,18 +1760,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness bc.reportBlock(block, nil, err) return nil, it.index, err } - // No validation errors for the first block (or chain prefix skipped) - var activeState *state.StateDB - defer func() { - // The chain importer is starting and stopping trie prefetchers. If a bad - // block or other error is hit however, an early return may not properly - // terminate the background threads. This defer ensures that we clean up - // and dangling prefetcher, without deferring each and holding on live refs. - if activeState != nil { - activeState.StopPrefetcher() - } - }() - // Track the singleton witness from this chain insertion (if any) var witness *stateless.Witness @@ -1825,63 +1815,20 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness continue } // Retrieve the parent block and it's state to execute on top - start := time.Now() parent := it.previous() if parent == nil { parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1) } - statedb, err := state.New(parent.Root, bc.statedb) - if err != nil { - return nil, it.index, err - } - - // If we are past Byzantium, enable prefetching to pull in trie node paths - // while processing transactions. Before Byzantium the prefetcher is mostly - // useless due to the intermediate root hashing after each transaction. - if bc.chainConfig.IsByzantium(block.Number()) { - // Generate witnesses either if we're self-testing, or if it's the - // only block being inserted. A bit crude, but witnesses are huge, - // so we refuse to make an entire chain of them. - if bc.vmConfig.StatelessSelfValidation || (makeWitness && len(chain) == 1) { - witness, err = stateless.NewWitness(block.Header(), bc) - if err != nil { - return nil, it.index, err - } - } - statedb.StartPrefetcher("chain", witness) - } - activeState = statedb - - // If we have a followup block, run that against the current state to pre-cache - // transactions and probabilistically some of the account/storage trie nodes. - var followupInterrupt atomic.Bool - if !bc.cacheConfig.TrieCleanNoPrefetch { - if followup, err := it.peek(); followup != nil && err == nil { - throwaway, _ := state.New(parent.Root, bc.statedb) - - go func(start time.Time, followup *types.Block, throwaway *state.StateDB) { - // Disable tracing for prefetcher executions. - vmCfg := bc.vmConfig - vmCfg.Tracer = nil - bc.prefetcher.Prefetch(followup, throwaway, vmCfg, &followupInterrupt) - - blockPrefetchExecuteTimer.Update(time.Since(start)) - if followupInterrupt.Load() { - blockPrefetchInterruptMeter.Mark(1) - } - }(time.Now(), followup, throwaway) - } - } - // The traced section of block import. - res, err := bc.processBlock(block, statedb, start, setHead) - followupInterrupt.Store(true) + start := time.Now() + res, err := bc.processBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1) if err != nil { return nil, it.index, err } // Report the import stats before returning the various results stats.processed++ stats.usedGas += res.usedGas + witness = res.witness var snapDiffItems, snapBufItems common.StorageSize if bc.snaps != nil { @@ -1937,11 +1884,74 @@ type blockProcessingResult struct { usedGas uint64 procTime time.Duration status WriteStatus + witness *stateless.Witness } // processBlock executes and validates the given block. If there was no error // it writes the block and associated state to database. -func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, start time.Time, setHead bool) (_ *blockProcessingResult, blockEndErr error) { +func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) { + var ( + err error + startTime = time.Now() + statedb *state.StateDB + interrupt atomic.Bool + ) + defer interrupt.Store(true) // terminate the prefetch at the end + + if bc.cacheConfig.TrieCleanNoPrefetch { + statedb, err = state.New(parentRoot, bc.statedb) + if err != nil { + return nil, err + } + } else { + // If prefetching is enabled, run that against the current state to pre-cache + // transactions and probabilistically some of the account/storage trie nodes. + // + // Note: the main processor and prefetcher share the same reader with a local + // cache for mitigating the overhead of state access. + reader, err := bc.statedb.ReaderWithCache(parentRoot) + if err != nil { + return nil, err + } + throwaway, err := state.NewWithReader(parentRoot, bc.statedb, reader) + if err != nil { + return nil, err + } + statedb, err = state.NewWithReader(parentRoot, bc.statedb, reader) + if err != nil { + return nil, err + } + go func(start time.Time, throwaway *state.StateDB, block *types.Block) { + // Disable tracing for prefetcher executions. + vmCfg := bc.vmConfig + vmCfg.Tracer = nil + bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt) + + blockPrefetchExecuteTimer.Update(time.Since(start)) + if interrupt.Load() { + blockPrefetchInterruptMeter.Mark(1) + } + }(time.Now(), throwaway, block) + } + + // If we are past Byzantium, enable prefetching to pull in trie node paths + // while processing transactions. Before Byzantium the prefetcher is mostly + // useless due to the intermediate root hashing after each transaction. + var witness *stateless.Witness + if bc.chainConfig.IsByzantium(block.Number()) { + // Generate witnesses either if we're self-testing, or if it's the + // only block being inserted. A bit crude, but witnesses are huge, + // so we refuse to make an entire chain of them. + if bc.vmConfig.StatelessSelfValidation || makeWitness { + witness, err = stateless.NewWitness(block.Header(), bc) + if err != nil { + return nil, err + } + } + statedb.StartPrefetcher("chain", witness) + defer statedb.StopPrefetcher() + } + if bc.logger != nil && bc.logger.OnBlockStart != nil { bc.logger.OnBlockStart(tracing.BlockEvent{ Block: block, @@ -2000,7 +2010,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s } } xvtime := time.Since(xvstart) - proctime := time.Since(start) // processing + validation + cross validation + proctime := time.Since(startTime) // processing + validation + cross validation // Update the metrics touched during block processing and validation accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing) @@ -2041,9 +2051,14 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits) - blockInsertTimer.UpdateSince(start) - - return &blockProcessingResult{usedGas: res.GasUsed, procTime: proctime, status: status}, nil + blockInsertTimer.UpdateSince(startTime) + + return &blockProcessingResult{ + usedGas: res.GasUsed, + procTime: proctime, + status: status, + witness: witness, + }, nil } // insertSideChain is called when an import batch hits upon a pruned ancestor diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index ec3f771818..b4bd444606 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -138,6 +138,7 @@ func (it *insertIterator) next() (*types.Block, error) { // // Both header and body validation errors (nil too) is cached into the iterator // to avoid duplicating work on the following next() call. +// nolint:unused func (it *insertIterator) peek() (*types.Block, error) { // If we reached the end of the chain, abort if it.index+1 >= len(it.chain) { diff --git a/core/state/database.go b/core/state/database.go index faf4954650..cef59cccfb 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -34,10 +34,10 @@ import ( const ( // Number of codehash->size associations to keep. - codeSizeCacheSize = 100000 + codeSizeCacheSize = 1_000_000 // 4 megabytes in total // Cache size granted for caching clean code. - codeCacheSize = 64 * 1024 * 1024 + codeCacheSize = 256 * 1024 * 1024 // Number of address->curve point associations to keep. pointCacheSize = 4096 @@ -208,6 +208,15 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) { return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil } +// ReaderWithCache creates a state reader with internal local cache. +func (db *CachingDB) ReaderWithCache(stateRoot common.Hash) (Reader, error) { + reader, err := db.Reader(stateRoot) + if err != nil { + return nil, err + } + return newReaderWithCache(reader), nil +} + // OpenTrie opens the main account trie at a specific root hash. func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) { if db.triedb.IsVerkle() { diff --git a/core/state/reader.go b/core/state/reader.go index a0f15dfcc8..5ad0385e9e 100644 --- a/core/state/reader.go +++ b/core/state/reader.go @@ -18,6 +18,7 @@ package state import ( "errors" + "sync" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/lru" @@ -32,6 +33,24 @@ import ( "github.com/ethereum/go-ethereum/triedb/database" ) +// bufferPool holds the buffers for keccak calculation. +var bufferPool = sync.Pool{ + New: func() interface{} { + return crypto.NewKeccakState() + }, +} + +// allocBuff allocates the keccak buffer from the pool +func allocBuff() crypto.KeccakState { + return bufferPool.Get().(crypto.KeccakState) +} + +// releaseBuff returns the provided keccak buffer to the pool. It's unnecessary +// to clear the buffer, as it will be cleared before the calculation. +func releaseBuff(buff crypto.KeccakState) { + bufferPool.Put(buff) +} + // ContractCodeReader defines the interface for accessing contract code. type ContractCodeReader interface { // Code retrieves a particular contract's code. @@ -51,6 +70,9 @@ type ContractCodeReader interface { // StateReader defines the interface for accessing accounts and storage slots // associated with a specific state. +// +// StateReader is assumed to be thread-safe and implementation must take care +// of the concurrency issue by themselves. type StateReader interface { // Account retrieves the account associated with a particular address. // @@ -70,6 +92,9 @@ type StateReader interface { // Reader defines the interface for accessing accounts, storage slots and contract // code associated with a specific state. +// +// Reader is assumed to be thread-safe and implementation must take care of the +// concurrency issue by themselves. type Reader interface { ContractCodeReader StateReader @@ -77,6 +102,8 @@ type Reader interface { // cachingCodeReader implements ContractCodeReader, accessing contract code either in // local key-value store or the shared code cache. +// +// cachingCodeReader is safe for concurrent access. type cachingCodeReader struct { db ethdb.KeyValueReader @@ -123,18 +150,14 @@ func (r *cachingCodeReader) CodeSize(addr common.Address, codeHash common.Hash) return len(code), nil } -// flatReader wraps a database state reader. +// flatReader wraps a database state reader and is safe for concurrent access. type flatReader struct { reader database.StateReader - buff crypto.KeccakState } // newFlatReader constructs a state reader with on the given state root. func newFlatReader(reader database.StateReader) *flatReader { - return &flatReader{ - reader: reader, - buff: crypto.NewKeccakState(), - } + return &flatReader{reader: reader} } // Account implements StateReader, retrieving the account specified by the address. @@ -144,7 +167,10 @@ func newFlatReader(reader database.StateReader) *flatReader { // // The returned account might be nil if it's not existent. func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) { - account, err := r.reader.Account(crypto.HashData(r.buff, addr.Bytes())) + buff := allocBuff() + defer releaseBuff(buff) + + account, err := r.reader.Account(crypto.HashData(buff, addr.Bytes())) if err != nil { return nil, err } @@ -174,8 +200,11 @@ func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) { // // The returned storage slot might be empty if it's not existent. func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) { - addrHash := crypto.HashData(r.buff, addr.Bytes()) - slotHash := crypto.HashData(r.buff, key.Bytes()) + buff := allocBuff() + defer releaseBuff(buff) + + addrHash := crypto.HashData(buff, addr.Bytes()) + slotHash := crypto.HashData(buff, key.Bytes()) ret, err := r.reader.Storage(addrHash, slotHash) if err != nil { return common.Hash{}, err @@ -196,13 +225,20 @@ func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, // trieReader implements the StateReader interface, providing functions to access // state from the referenced trie. +// +// trieReader is safe for concurrent read. type trieReader struct { - root common.Hash // State root which uniquely represent a state - db *triedb.Database // Database for loading trie - buff crypto.KeccakState // Buffer for keccak256 hashing - mainTrie Trie // Main trie, resolved in constructor + root common.Hash // State root which uniquely represent a state + db *triedb.Database // Database for loading trie + buff crypto.KeccakState // Buffer for keccak256 hashing + + // Main trie, resolved in constructor. Note either the Merkle-Patricia-tree + // or Verkle-tree is not safe for concurrent read. + mainTrie Trie + subRoots map[common.Address]common.Hash // Set of storage roots, cached when the account is resolved subTries map[common.Address]Trie // Group of storage tries, cached when it's resolved + lock sync.Mutex // Lock for protecting concurrent read } // trieReader constructs a trie reader of the specific state. An error will be @@ -230,11 +266,8 @@ func newTrieReader(root common.Hash, db *triedb.Database, cache *utils.PointCach }, nil } -// Account implements StateReader, retrieving the account specified by the address. -// -// An error will be returned if the trie state is corrupted. An nil account -// will be returned if it's not existent in the trie. -func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) { +// account is the inner version of Account and assumes the r.lock is already held. +func (r *trieReader) account(addr common.Address) (*types.StateAccount, error) { account, err := r.mainTrie.GetAccount(addr) if err != nil { return nil, err @@ -247,12 +280,26 @@ func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) { return account, nil } +// Account implements StateReader, retrieving the account specified by the address. +// +// An error will be returned if the trie state is corrupted. An nil account +// will be returned if it's not existent in the trie. +func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) { + r.lock.Lock() + defer r.lock.Unlock() + + return r.account(addr) +} + // Storage implements StateReader, retrieving the storage slot specified by the // address and slot key. // // An error will be returned if the trie state is corrupted. An empty storage // slot will be returned if it's not existent in the trie. func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) { + r.lock.Lock() + defer r.lock.Unlock() + var ( tr Trie found bool @@ -268,7 +315,7 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, // The storage slot is accessed without account caching. It's unexpected // behavior but try to resolve the account first anyway. if !ok { - _, err := r.Account(addr) + _, err := r.account(addr) if err != nil { return common.Hash{}, err } @@ -293,6 +340,9 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, // multiStateReader is the aggregation of a list of StateReader interface, // providing state access by leveraging all readers. The checking priority // is determined by the position in the reader list. +// +// multiStateReader is safe for concurrent read and assumes all underlying +// readers are thread-safe as well. type multiStateReader struct { readers []StateReader // List of state readers, sorted by checking priority } @@ -358,3 +408,95 @@ func newReader(codeReader ContractCodeReader, stateReader StateReader) *reader { StateReader: stateReader, } } + +// readerWithCache is a wrapper around Reader that maintains additional state caches +// to support concurrent state access. +type readerWithCache struct { + Reader // safe for concurrent read + + // Previously resolved state entries. + accounts map[common.Address]*types.StateAccount + accountLock sync.RWMutex + + // List of storage buckets, each of which is thread-safe. + // This reader is typically used in scenarios requiring concurrent + // access to storage. Using multiple buckets helps mitigate + // the overhead caused by locking. + storageBuckets [16]struct { + lock sync.RWMutex + storages map[common.Address]map[common.Hash]common.Hash + } +} + +// newReaderWithCache constructs the reader with local cache. +func newReaderWithCache(reader Reader) *readerWithCache { + r := &readerWithCache{ + Reader: reader, + accounts: make(map[common.Address]*types.StateAccount), + } + for i := range r.storageBuckets { + r.storageBuckets[i].storages = make(map[common.Address]map[common.Hash]common.Hash) + } + return r +} + +// Account implements StateReader, retrieving the account specified by the address. +// The returned account might be nil if it's not existent. +// +// An error will be returned if the state is corrupted in the underlying reader. +func (r *readerWithCache) Account(addr common.Address) (*types.StateAccount, error) { + // Try to resolve the requested account in the local cache + r.accountLock.RLock() + acct, ok := r.accounts[addr] + r.accountLock.RUnlock() + if ok { + return acct, nil + } + // Try to resolve the requested account from the underlying reader + acct, err := r.Reader.Account(addr) + if err != nil { + return nil, err + } + r.accountLock.Lock() + r.accounts[addr] = acct + r.accountLock.Unlock() + return acct, nil +} + +// Storage implements StateReader, retrieving the storage slot specified by the +// address and slot key. The returned storage slot might be empty if it's not +// existent. +// +// An error will be returned if the state is corrupted in the underlying reader. +func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common.Hash, error) { + var ( + value common.Hash + ok bool + bucket = &r.storageBuckets[addr[0]&0x0f] + ) + // Try to resolve the requested storage slot in the local cache + bucket.lock.RLock() + slots, ok := bucket.storages[addr] + if ok { + value, ok = slots[slot] + } + bucket.lock.RUnlock() + if ok { + return value, nil + } + // Try to resolve the requested storage slot from the underlying reader + value, err := r.Reader.Storage(addr, slot) + if err != nil { + return common.Hash{}, err + } + bucket.lock.Lock() + slots, ok = bucket.storages[addr] + if !ok { + slots = make(map[common.Hash]common.Hash) + bucket.storages[addr] = slots + } + slots[slot] = value + bucket.lock.Unlock() + + return value, nil +} diff --git a/core/state/statedb.go b/core/state/statedb.go index e3f5b9e1a0..9378cae7de 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -159,11 +159,17 @@ type StateDB struct { // New creates a new state from a given trie. func New(root common.Hash, db Database) (*StateDB, error) { - tr, err := db.OpenTrie(root) + reader, err := db.Reader(root) if err != nil { return nil, err } - reader, err := db.Reader(root) + return NewWithReader(root, db, reader) +} + +// NewWithReader creates a new state for the specified state root. Unlike New, +// this function accepts an additional Reader which is bound to the given root. +func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, error) { + tr, err := db.OpenTrie(root) if err != nil { return nil, err } @@ -392,6 +398,12 @@ func (s *StateDB) Database() Database { return s.db } +// Reader retrieves the low level database reader supporting the +// lower level operations. +func (s *StateDB) Reader() Reader { + return s.reader +} + func (s *StateDB) HasSelfDestructed(addr common.Address) bool { stateObject := s.getStateObject(addr) if stateObject != nil { @@ -650,11 +662,10 @@ func (s *StateDB) CreateContract(addr common.Address) { // Snapshots of the copied state cannot be applied to the copy. func (s *StateDB) Copy() *StateDB { // Copy all the basic fields, initialize the memory ones - reader, _ := s.db.Reader(s.originalRoot) // impossible to fail state := &StateDB{ db: s.db, trie: mustCopyTrie(s.trie), - reader: reader, + reader: s.reader, originalRoot: s.originalRoot, stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)), stateObjectsDestruct: make(map[common.Address]*stateObject, len(s.stateObjectsDestruct)), diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 805df5ef62..f3129f57cd 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -17,17 +17,22 @@ package core import ( + "bytes" + "runtime" "sync/atomic" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" + "golang.org/x/sync/errgroup" ) -// statePrefetcher is a basic Prefetcher, which blindly executes a block on top -// of an arbitrary state with the goal of prefetching potentially useful state -// data from disk before the main block processor start executing. +// statePrefetcher is a basic Prefetcher that executes transactions from a block +// on top of the parent state, aiming to prefetch potentially useful state data +// from disk. Transactions are executed in parallel to fully leverage the +// SSD's read performance. type statePrefetcher struct { config *params.ChainConfig // Chain configuration options chain *HeaderChain // Canonical block chain @@ -43,41 +48,81 @@ func newStatePrefetcher(config *params.ChainConfig, chain *HeaderChain) *statePr // Prefetch processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb, but any changes are discarded. The -// only goal is to pre-cache transaction signatures and state trie nodes. +// only goal is to warm the state caches. func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) { var ( - header = block.Header() - gaspool = new(GasPool).AddGas(block.GasLimit()) - blockContext = NewEVMBlockContext(header, p.chain, nil) - evm = vm.NewEVM(blockContext, statedb, p.config, cfg) - signer = types.MakeSigner(p.config, header.Number, header.Time) + fails atomic.Int64 + header = block.Header() + signer = types.MakeSigner(p.config, header.Number, header.Time) + workers errgroup.Group + reader = statedb.Reader() ) + workers.SetLimit(runtime.NumCPU() / 2) + // Iterate over and process the individual transactions - byzantium := p.config.IsByzantium(block.Number()) for i, tx := range block.Transactions() { - // If block precaching was interrupted, abort - if interrupt != nil && interrupt.Load() { - return - } - // Convert the transaction into an executable message and pre-cache its sender - msg, err := TransactionToMessage(tx, signer, header.BaseFee) - if err != nil { - return // Also invalid block, bail out - } - statedb.SetTxContext(tx.Hash(), i) + stateCpy := statedb.Copy() // closure + workers.Go(func() error { + // If block precaching was interrupted, abort + if interrupt != nil && interrupt.Load() { + return nil + } + // Preload the touched accounts and storage slots in advance + sender, err := types.Sender(signer, tx) + if err != nil { + fails.Add(1) + return nil + } + reader.Account(sender) - // We attempt to apply a transaction. The goal is not to execute - // the transaction successfully, rather to warm up touched data slots. - if _, err := ApplyMessage(evm, msg, gaspool); err != nil { - return // Ugh, something went horribly wrong, bail out - } - // If we're pre-byzantium, pre-load trie nodes for the intermediate root - if !byzantium { - statedb.IntermediateRoot(true) - } - } - // If were post-byzantium, pre-load trie nodes for the final root hash - if byzantium { - statedb.IntermediateRoot(true) + if tx.To() != nil { + account, _ := reader.Account(*tx.To()) + + // Preload the contract code if the destination has non-empty code + if account != nil && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { + reader.Code(*tx.To(), common.BytesToHash(account.CodeHash)) + } + } + for _, list := range tx.AccessList() { + reader.Account(list.Address) + if len(list.StorageKeys) > 0 { + for _, slot := range list.StorageKeys { + reader.Storage(list.Address, slot) + } + } + } + // Execute the message to preload the implicit touched states + evm := vm.NewEVM(NewEVMBlockContext(header, p.chain, nil), stateCpy, p.config, cfg) + + // Convert the transaction into an executable message and pre-cache its sender + msg, err := TransactionToMessage(tx, signer, header.BaseFee) + if err != nil { + fails.Add(1) + return nil // Also invalid block, bail out + } + // Disable the nonce check + msg.SkipNonceChecks = true + + stateCpy.SetTxContext(tx.Hash(), i) + + // We attempt to apply a transaction. The goal is not to execute + // the transaction successfully, rather to warm up touched data slots. + if _, err := ApplyMessage(evm, msg, new(GasPool).AddGas(block.GasLimit())); err != nil { + fails.Add(1) + return nil // Ugh, something went horribly wrong, bail out + } + // Pre-load trie nodes for the intermediate root. + // + // This operation incurs significant memory allocations due to + // trie hashing and node decoding. TODO(rjl493456442): investigate + // ways to mitigate this overhead. + stateCpy.IntermediateRoot(true) + return nil + }) } + workers.Wait() + + blockPrefetchTxsValidMeter.Mark(int64(len(block.Transactions())) - fails.Load()) + blockPrefetchTxsInvalidMeter.Mark(fails.Load()) + return } diff --git a/core/state_transition.go b/core/state_transition.go index f9c9a2ab5a..ff2051ddd2 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -159,7 +159,9 @@ type Message struct { // When SkipNonceChecks is true, the message nonce is not checked against the // account nonce in state. - // This field will be set to true for operations like RPC eth_call. + // + // This field will be set to true for operations like RPC eth_call + // or the state prefetching. SkipNonceChecks bool // When SkipFromEOACheck is true, the message sender is not checked to be an EOA. diff --git a/triedb/pathdb/metrics.go b/triedb/pathdb/metrics.go index 45dad6f1ae..abe2dfe1f6 100644 --- a/triedb/pathdb/metrics.go +++ b/triedb/pathdb/metrics.go @@ -46,7 +46,7 @@ var ( nodeDiskFalseMeter = metrics.NewRegisteredMeter("pathdb/disk/false", nil) nodeDiffFalseMeter = metrics.NewRegisteredMeter("pathdb/diff/false", nil) - commitTimeTimer = metrics.NewRegisteredTimer("pathdb/commit/time", nil) + commitTimeTimer = metrics.NewRegisteredResettingTimer("pathdb/commit/time", nil) commitNodesMeter = metrics.NewRegisteredMeter("pathdb/commit/nodes", nil) commitBytesMeter = metrics.NewRegisteredMeter("pathdb/commit/bytes", nil) @@ -57,7 +57,7 @@ var ( gcStorageMeter = metrics.NewRegisteredMeter("pathdb/gc/storage/count", nil) gcStorageBytesMeter = metrics.NewRegisteredMeter("pathdb/gc/storage/bytes", nil) - historyBuildTimeMeter = metrics.NewRegisteredTimer("pathdb/history/time", nil) + historyBuildTimeMeter = metrics.NewRegisteredResettingTimer("pathdb/history/time", nil) historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil) historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil) ) From 0eb2eeea908d654b971249142fcbb735ba2c6923 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Fri, 9 May 2025 07:52:40 +0200 Subject: [PATCH 012/365] all: create global hasher pool (#31769) This PR creates a global hasher pool that can be used by all packages. It also removes a bunch of the package local pools. It also updates a few locations to use available hashers or the global hashing pool to reduce allocations all over the codebase. This change should reduce global allocation count by ~1% --------- Co-authored-by: Gary Rong --- core/rawdb/accessors_trie.go | 28 ++-------------------------- core/state/reader.go | 30 +++--------------------------- core/types/hashing.go | 3 +-- core/vm/evm.go | 3 ++- core/vm/instructions.go | 7 +------ core/vm/interpreter.go | 2 +- crypto/crypto.go | 15 +++++++++++++-- trie/hasher.go | 2 +- trie/sync.go | 24 +----------------------- triedb/pathdb/disklayer.go | 26 ++------------------------ triedb/pathdb/execute.go | 15 +++++++-------- 11 files changed, 34 insertions(+), 121 deletions(-) diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go index 8bd6b71eee..e154ab527b 100644 --- a/core/rawdb/accessors_trie.go +++ b/core/rawdb/accessors_trie.go @@ -18,7 +18,6 @@ package rawdb import ( "fmt" - "sync" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -45,25 +44,6 @@ const HashScheme = "hash" // on extra state diffs to survive deep reorg. const PathScheme = "path" -// hasher is used to compute the sha256 hash of the provided data. -type hasher struct{ sha crypto.KeccakState } - -var hasherPool = sync.Pool{ - New: func() interface{} { return &hasher{sha: crypto.NewKeccakState()} }, -} - -func newHasher() *hasher { - return hasherPool.Get().(*hasher) -} - -func (h *hasher) hash(data []byte) common.Hash { - return crypto.HashData(h.sha, data) -} - -func (h *hasher) release() { - hasherPool.Put(h) -} - // ReadAccountTrieNode retrieves the account trie node with the specified node path. func ReadAccountTrieNode(db ethdb.KeyValueReader, path []byte) []byte { data, _ := db.Get(accountTrieNodeKey(path)) @@ -170,9 +150,7 @@ func HasTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash c if len(blob) == 0 { return false } - h := newHasher() - defer h.release() - return h.hash(blob) == hash // exists but not match + return crypto.Keccak256Hash(blob) == hash // exists but not match default: panic(fmt.Sprintf("Unknown scheme %v", scheme)) } @@ -194,9 +172,7 @@ func ReadTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash if len(blob) == 0 { return nil } - h := newHasher() - defer h.release() - if h.hash(blob) != hash { + if crypto.Keccak256Hash(blob) != hash { return nil // exists but not match } return blob diff --git a/core/state/reader.go b/core/state/reader.go index 5ad0385e9e..09edf6ab8d 100644 --- a/core/state/reader.go +++ b/core/state/reader.go @@ -33,24 +33,6 @@ import ( "github.com/ethereum/go-ethereum/triedb/database" ) -// bufferPool holds the buffers for keccak calculation. -var bufferPool = sync.Pool{ - New: func() interface{} { - return crypto.NewKeccakState() - }, -} - -// allocBuff allocates the keccak buffer from the pool -func allocBuff() crypto.KeccakState { - return bufferPool.Get().(crypto.KeccakState) -} - -// releaseBuff returns the provided keccak buffer to the pool. It's unnecessary -// to clear the buffer, as it will be cleared before the calculation. -func releaseBuff(buff crypto.KeccakState) { - bufferPool.Put(buff) -} - // ContractCodeReader defines the interface for accessing contract code. type ContractCodeReader interface { // Code retrieves a particular contract's code. @@ -167,10 +149,7 @@ func newFlatReader(reader database.StateReader) *flatReader { // // The returned account might be nil if it's not existent. func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) { - buff := allocBuff() - defer releaseBuff(buff) - - account, err := r.reader.Account(crypto.HashData(buff, addr.Bytes())) + account, err := r.reader.Account(crypto.Keccak256Hash(addr.Bytes())) if err != nil { return nil, err } @@ -200,11 +179,8 @@ func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) { // // The returned storage slot might be empty if it's not existent. func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) { - buff := allocBuff() - defer releaseBuff(buff) - - addrHash := crypto.HashData(buff, addr.Bytes()) - slotHash := crypto.HashData(buff, key.Bytes()) + addrHash := crypto.Keccak256Hash(addr.Bytes()) + slotHash := crypto.Keccak256Hash(key.Bytes()) ret, err := r.reader.Storage(addrHash, slotHash) if err != nil { return common.Hash{}, err diff --git a/core/types/hashing.go b/core/types/hashing.go index 224d7a87ea..3cc22d50d1 100644 --- a/core/types/hashing.go +++ b/core/types/hashing.go @@ -25,12 +25,11 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/sha3" ) // hasherPool holds LegacyKeccak256 hashers for rlpHash. var hasherPool = sync.Pool{ - New: func() interface{} { return sha3.NewLegacyKeccak256() }, + New: func() interface{} { return crypto.NewKeccakState() }, } // encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding. diff --git a/core/vm/evm.go b/core/vm/evm.go index c28dcb2554..ecb0f118ec 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -555,7 +555,8 @@ func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *ui // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), crypto.Keccak256(code)) + inithash := crypto.HashData(evm.interpreter.hasher, code) + contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash[:]) return evm.create(caller, code, gas, endowment, contractAddr, CREATE2) } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 0b3b1d1569..63bb6d2d51 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -22,7 +22,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" ) @@ -234,11 +233,7 @@ func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ( offset, size := scope.Stack.pop(), scope.Stack.peek() data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64()) - if interpreter.hasher == nil { - interpreter.hasher = crypto.NewKeccakState() - } else { - interpreter.hasher.Reset() - } + interpreter.hasher.Reset() interpreter.hasher.Write(data) interpreter.hasher.Read(interpreter.hasherBuf[:]) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index a0038d1aa8..a62c3c843d 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -150,7 +150,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { } } evm.Config.ExtraEips = extraEips - return &EVMInterpreter{evm: evm, table: table} + return &EVMInterpreter{evm: evm, table: table, hasher: crypto.NewKeccakState()} } // Run loops and evaluates the contract's code with the given input data and returns diff --git a/crypto/crypto.go b/crypto/crypto.go index 13e9b134f0..09596c05ce 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -28,6 +28,7 @@ import ( "io" "math/big" "os" + "sync" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" @@ -73,6 +74,12 @@ func NewKeccakState() KeccakState { return sha3.NewLegacyKeccak256().(KeccakState) } +var hasherPool = sync.Pool{ + New: func() any { + return sha3.NewLegacyKeccak256().(KeccakState) + }, +} + // HashData hashes the provided data using the KeccakState and returns a 32 byte hash func HashData(kh KeccakState, data []byte) (h common.Hash) { kh.Reset() @@ -84,22 +91,26 @@ func HashData(kh KeccakState, data []byte) (h common.Hash) { // Keccak256 calculates and returns the Keccak256 hash of the input data. func Keccak256(data ...[]byte) []byte { b := make([]byte, 32) - d := NewKeccakState() + d := hasherPool.Get().(KeccakState) + d.Reset() for _, b := range data { d.Write(b) } d.Read(b) + hasherPool.Put(d) return b } // Keccak256Hash calculates and returns the Keccak256 hash of the input data, // converting it to an internal Hash data structure. func Keccak256Hash(data ...[]byte) (h common.Hash) { - d := NewKeccakState() + d := hasherPool.Get().(KeccakState) + d.Reset() for _, b := range data { d.Write(b) } d.Read(h[:]) + hasherPool.Put(d) return h } diff --git a/trie/hasher.go b/trie/hasher.go index 614640ae3a..393cb0bd4d 100644 --- a/trie/hasher.go +++ b/trie/hasher.go @@ -34,7 +34,7 @@ type hasher struct { // hasherPool holds pureHashers var hasherPool = sync.Pool{ - New: func() interface{} { + New: func() any { return &hasher{ tmp: make([]byte, 0, 550), // cap is as large as a full fullNode. sha: crypto.NewKeccakState(), diff --git a/trie/sync.go b/trie/sync.go index 3b7caae5b1..8d0ce6901c 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -729,9 +729,7 @@ func (s *Sync) hasNode(owner common.Hash, path []byte, hash common.Hash) (exists } else { blob = rawdb.ReadStorageTrieNode(s.database, owner, path) } - h := newBlobHasher() - defer h.release() - exists = hash == h.hash(blob) + exists = hash == crypto.Keccak256Hash(blob) inconsistent = !exists && len(blob) != 0 return exists, inconsistent } @@ -746,23 +744,3 @@ func ResolvePath(path []byte) (common.Hash, []byte) { } return owner, path } - -// blobHasher is used to compute the sha256 hash of the provided data. -type blobHasher struct{ state crypto.KeccakState } - -// blobHasherPool is the pool for reusing pre-allocated hash state. -var blobHasherPool = sync.Pool{ - New: func() interface{} { return &blobHasher{state: crypto.NewKeccakState()} }, -} - -func newBlobHasher() *blobHasher { - return blobHasherPool.Get().(*blobHasher) -} - -func (h *blobHasher) hash(data []byte) common.Hash { - return crypto.HashData(h.state, data) -} - -func (h *blobHasher) release() { - blobHasherPool.Put(h) -} diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index f3a60a507d..b8869888d9 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -115,15 +115,12 @@ func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co dirtyNodeMissMeter.Mark(1) // Try to retrieve the trie node from the clean memory cache - h := newHasher() - defer h.release() - key := nodeCacheKey(owner, path) if dl.nodes != nil { if blob := dl.nodes.Get(nil, key); len(blob) > 0 { cleanNodeHitMeter.Mark(1) cleanNodeReadMeter.Mark(int64(len(blob))) - return blob, h.hash(blob), &nodeLoc{loc: locCleanCache, depth: depth}, nil + return blob, crypto.Keccak256Hash(blob), &nodeLoc{loc: locCleanCache, depth: depth}, nil } cleanNodeMissMeter.Mark(1) } @@ -138,7 +135,7 @@ func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co dl.nodes.Set(key, blob) cleanNodeWriteMeter.Mark(int64(len(blob))) } - return blob, h.hash(blob), &nodeLoc{loc: locDiskLayer, depth: depth}, nil + return blob, crypto.Keccak256Hash(blob), &nodeLoc{loc: locDiskLayer, depth: depth}, nil } // account directly retrieves the account RLP associated with a particular @@ -359,22 +356,3 @@ func (dl *diskLayer) resetCache() { dl.nodes.Reset() } } - -// hasher is used to compute the sha256 hash of the provided data. -type hasher struct{ sha crypto.KeccakState } - -var hasherPool = sync.Pool{ - New: func() interface{} { return &hasher{sha: crypto.NewKeccakState()} }, -} - -func newHasher() *hasher { - return hasherPool.Get().(*hasher) -} - -func (h *hasher) hash(data []byte) common.Hash { - return crypto.HashData(h.sha, data) -} - -func (h *hasher) release() { - hasherPool.Put(h) -} diff --git a/triedb/pathdb/execute.go b/triedb/pathdb/execute.go index 2400f280a3..db1e679277 100644 --- a/triedb/pathdb/execute.go +++ b/triedb/pathdb/execute.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/trienode" @@ -85,10 +86,9 @@ func apply(db database.NodeDatabase, prevRoot common.Hash, postRoot common.Hash, func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) error { // The account was present in prev-state, decode it from the // 'slim-rlp' format bytes. - h := newHasher() - defer h.release() + h := crypto.NewKeccakState() - addrHash := h.hash(addr.Bytes()) + addrHash := crypto.HashData(h, addr.Bytes()) prev, err := types.FullAccount(ctx.accounts[addr]) if err != nil { return err @@ -113,7 +113,7 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) for key, val := range ctx.storages[addr] { tkey := key if ctx.rawStorageKey { - tkey = h.hash(key.Bytes()) + tkey = crypto.HashData(h, key.Bytes()) } var err error if len(val) == 0 { @@ -149,10 +149,9 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) // account and storage is wiped out correctly. func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address) error { // The account must be existent in post-state, load the account. - h := newHasher() - defer h.release() + h := crypto.NewKeccakState() - addrHash := h.hash(addr.Bytes()) + addrHash := crypto.HashData(h, addr.Bytes()) blob, err := ctx.accountTrie.Get(addrHash.Bytes()) if err != nil { return err @@ -174,7 +173,7 @@ func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address) } tkey := key if ctx.rawStorageKey { - tkey = h.hash(key.Bytes()) + tkey = crypto.HashData(h, key.Bytes()) } if err := st.Delete(tkey.Bytes()); err != nil { return err From 0db99f4e409b05c109cffac26c15dd641757a3ab Mon Sep 17 00:00:00 2001 From: Satoshi Is Here <39875249+SatoshiIsHere@users.noreply.github.com> Date: Fri, 9 May 2025 19:56:00 +0900 Subject: [PATCH 013/365] core/types: reduce allocations in tx.EffectiveGasTip (#31598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR introduces an allocation-free version of the Transaction.EffectiveGasTip method to improve performance by reducing memory allocations. ## Changes - Added a new `EffectiveGasTipInto` method that accepts a destination parameter to avoid memory allocations - Refactored the existing `EffectiveGasTip` method to use the new allocation-free implementation - Updated related methods (`EffectiveGasTipValue`, `EffectiveGasTipCmp`, `EffectiveGasTipIntCmp`) to use the allocation-free approach - Added tests and benchmarks to verify correctness and measure performance improvements ## Motivation In high-transaction-volume environments, the `EffectiveGasTip` method is called frequently. Reducing memory allocations in this method decreases garbage collection pressure and improves overall system performance. ## Benchmark Results As-Is BenchmarkEffectiveGasTip/Original-10 42089140 27.45 ns/op 8 B/op 1 allocs/op To-Be BenchmarkEffectiveGasTip/IntoMethod-10 72353263 16.73 ns/op 0 B/op 0 allocs/op ## Summary of Improvements - **Performance**: ~39% faster execution (27.45 ns/op → 16.73 ns/op) - **Memory**: Eliminated all allocations (8 B/op → 0 B/op) - **Allocation count**: Reduced from 1 to 0 allocations per operation This optimization follows the same pattern successfully applied to other methods in the codebase, maintaining API compatibility while improving performance. ## Safety & Compatibility This optimization has no side effects or adverse impacts because: - It maintains functional equivalence as confirmed by comprehensive tests - It preserves API compatibility with existing callers - It follows clear memory ownership patterns with the destination parameter - It maintains thread safety by only modifying the caller-provided destination parameter This optimization follows the same pattern successfully applied to other methods in the codebase, providing better performance without compromising stability or correctness. --------- Co-authored-by: lightclient --- core/types/transaction.go | 41 ++++++++------ core/types/transaction_test.go | 99 ++++++++++++++++++++++++++++++++++ eth/tracers/js/goja.go | 3 +- 3 files changed, 126 insertions(+), 17 deletions(-) diff --git a/core/types/transaction.go b/core/types/transaction.go index a2f4104635..934feb7353 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -355,28 +355,31 @@ func (tx *Transaction) GasTipCapIntCmp(other *big.Int) int { // Note: if the effective gasTipCap is negative, this method returns both error // the actual negative value, _and_ ErrGasFeeCapTooLow func (tx *Transaction) EffectiveGasTip(baseFee *big.Int) (*big.Int, error) { + dst := new(big.Int) + err := tx.calcEffectiveGasTip(dst, baseFee) + return dst, err +} + +// calcEffectiveGasTip calculates the effective gas tip of the transaction and +// saves the result to dst. +func (tx *Transaction) calcEffectiveGasTip(dst *big.Int, baseFee *big.Int) error { if baseFee == nil { - return tx.GasTipCap(), nil + dst.Set(tx.inner.gasTipCap()) + return nil } + var err error - gasFeeCap := tx.GasFeeCap() + gasFeeCap := tx.inner.gasFeeCap() if gasFeeCap.Cmp(baseFee) < 0 { err = ErrGasFeeCapTooLow } - gasFeeCap = gasFeeCap.Sub(gasFeeCap, baseFee) - gasTipCap := tx.GasTipCap() - if gasTipCap.Cmp(gasFeeCap) < 0 { - return gasTipCap, err + dst.Sub(gasFeeCap, baseFee) + gasTipCap := tx.inner.gasTipCap() + if gasTipCap.Cmp(dst) < 0 { + dst.Set(gasTipCap) } - return gasFeeCap, err -} - -// EffectiveGasTipValue is identical to EffectiveGasTip, but does not return an -// error in case the effective gasTipCap is negative -func (tx *Transaction) EffectiveGasTipValue(baseFee *big.Int) *big.Int { - effectiveTip, _ := tx.EffectiveGasTip(baseFee) - return effectiveTip + return err } // EffectiveGasTipCmp compares the effective gasTipCap of two transactions assuming the given base fee. @@ -384,7 +387,11 @@ func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *big.Int) if baseFee == nil { return tx.GasTipCapCmp(other) } - return tx.EffectiveGasTipValue(baseFee).Cmp(other.EffectiveGasTipValue(baseFee)) + // Use more efficient internal method. + txTip, otherTip := new(big.Int), new(big.Int) + tx.calcEffectiveGasTip(txTip, baseFee) + other.calcEffectiveGasTip(otherTip, baseFee) + return txTip.Cmp(otherTip) } // EffectiveGasTipIntCmp compares the effective gasTipCap of a transaction to the given gasTipCap. @@ -392,7 +399,9 @@ func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, baseFee *big.Int) i if baseFee == nil { return tx.GasTipCapIntCmp(other) } - return tx.EffectiveGasTipValue(baseFee).Cmp(other) + txTip := new(big.Int) + tx.calcEffectiveGasTip(txTip, baseFee) + return txTip.Cmp(other) } // BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise. diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 8922448d97..7d5e2f058a 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) @@ -593,3 +594,101 @@ func BenchmarkHash(b *testing.B) { signer.Hash(tx) } } + +func BenchmarkEffectiveGasTip(b *testing.B) { + signer := LatestSigner(params.TestChainConfig) + key, _ := crypto.GenerateKey() + txdata := &DynamicFeeTx{ + ChainID: big.NewInt(1), + Nonce: 0, + GasTipCap: big.NewInt(2000000000), + GasFeeCap: big.NewInt(3000000000), + Gas: 21000, + To: &common.Address{}, + Value: big.NewInt(0), + Data: nil, + } + tx, _ := SignNewTx(key, signer, txdata) + baseFee := big.NewInt(1000000000) // 1 gwei + + b.Run("Original", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := tx.EffectiveGasTip(baseFee) + if err != nil { + b.Fatal(err) + } + } + }) + + b.Run("IntoMethod", func(b *testing.B) { + b.ReportAllocs() + dst := new(big.Int) + for i := 0; i < b.N; i++ { + err := tx.calcEffectiveGasTip(dst, baseFee) + if err != nil { + b.Fatal(err) + } + } + }) +} + +func TestEffectiveGasTipInto(t *testing.T) { + signer := LatestSigner(params.TestChainConfig) + key, _ := crypto.GenerateKey() + + testCases := []struct { + tipCap int64 + feeCap int64 + baseFee *int64 + }{ + {tipCap: 1, feeCap: 100, baseFee: intPtr(50)}, + {tipCap: 10, feeCap: 100, baseFee: intPtr(50)}, + {tipCap: 50, feeCap: 100, baseFee: intPtr(50)}, + {tipCap: 100, feeCap: 100, baseFee: intPtr(50)}, + {tipCap: 1, feeCap: 50, baseFee: intPtr(50)}, + {tipCap: 1, feeCap: 20, baseFee: intPtr(50)}, // Base fee higher than fee cap + {tipCap: 50, feeCap: 100, baseFee: intPtr(0)}, + {tipCap: 50, feeCap: 100, baseFee: nil}, // nil base fee + } + + for i, tc := range testCases { + txdata := &DynamicFeeTx{ + ChainID: big.NewInt(1), + Nonce: 0, + GasTipCap: big.NewInt(tc.tipCap), + GasFeeCap: big.NewInt(tc.feeCap), + Gas: 21000, + To: &common.Address{}, + Value: big.NewInt(0), + Data: nil, + } + tx, _ := SignNewTx(key, signer, txdata) + + var baseFee *big.Int + if tc.baseFee != nil { + baseFee = big.NewInt(*tc.baseFee) + } + + // Get result from original method + orig, origErr := tx.EffectiveGasTip(baseFee) + + // Get result from new method + dst := new(big.Int) + newErr := tx.calcEffectiveGasTip(dst, baseFee) + + // Compare results + if (origErr != nil) != (newErr != nil) { + t.Fatalf("case %d: error mismatch: orig %v, new %v", i, origErr, newErr) + } + + if orig.Cmp(dst) != 0 { + t.Fatalf("case %d: result mismatch: orig %v, new %v", i, orig, dst) + } + } +} + +// Helper function to create integer pointer +func intPtr(i int64) *int64 { + return &i +} diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index 227ea57226..d1e65bf7f4 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -260,7 +260,8 @@ func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from t.activePrecompiles = vm.ActivePrecompiles(rules) t.ctx["block"] = t.vm.ToValue(t.env.BlockNumber.Uint64()) t.ctx["gas"] = t.vm.ToValue(tx.Gas()) - gasPriceBig, err := t.toBig(t.vm, tx.EffectiveGasTipValue(env.BaseFee).String()) + gasTip, _ := tx.EffectiveGasTip(env.BaseFee) + gasPriceBig, err := t.toBig(t.vm, gasTip.String()) if err != nil { t.err = err return From fa86416ce914d36464f1af31fae0e6c8a8c65f69 Mon Sep 17 00:00:00 2001 From: Marcel <153717436+MonkeyMarcel@users.noreply.github.com> Date: Sat, 10 May 2025 08:27:27 +0800 Subject: [PATCH 014/365] metrics: add chain/mgasps to track gas usage rate (#31753) This adds a metric called `chain/mgasps`, which records how many million gas per second are being used during block insertion. The value is calculated as `usedGas * 1000 / elapsed`, and it's updated in the `insertStats.report` method. Also cleaned up the log output to reuse the same value instead of recalculating it. Useful for monitoring block processing throughput. --------- Co-authored-by: Gary Rong --- core/blockchain.go | 3 ++- core/blockchain_insert.go | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 3c691600eb..302ab14cf0 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -65,7 +65,8 @@ var ( headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil) headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil) - chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil) + chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil) + chainMgaspsGauge = metrics.NewRegisteredGauge("chain/mgasps", nil) accountReadTimer = metrics.NewRegisteredResettingTimer("chain/account/reads", nil) accountHashTimer = metrics.NewRegisteredResettingTimer("chain/account/hashes", nil) diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index b4bd444606..695aa6679b 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -43,8 +43,12 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn // Fetch the timings for the batch var ( now = mclock.Now() - elapsed = now.Sub(st.startTime) + elapsed = now.Sub(st.startTime) + 1 // prevent zero division + mgasps = float64(st.usedGas) * 1000 / float64(elapsed) ) + // Update the Mgas per second gauge + chainMgaspsGauge.Update(int64(mgasps)) + // If we're at the last block of the batch or report period reached, log if index == len(chain)-1 || elapsed >= statsReportLimit { // Count the number of transactions in this segment @@ -58,7 +62,7 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn context := []interface{}{ "number", end.Number(), "hash", end.Hash(), "blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000, - "elapsed", common.PrettyDuration(elapsed), "mgasps", float64(st.usedGas) * 1000 / float64(elapsed), + "elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps, } if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute { context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) From 098cc7e8782178f5f34b9101550ec2f43831188d Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Mon, 12 May 2025 14:37:01 +0800 Subject: [PATCH 015/365] ethdb/pebble: expose stall counter of pebble (#31782) This pull request adds a more Pebble metrics, tracking the amount of write stalls with specific reasons --- ethdb/pebble/pebble.go | 91 +++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index 9ece995655..5c851af910 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -21,6 +21,7 @@ import ( "bytes" "fmt" "runtime" + "strings" "sync" "sync/atomic" "time" @@ -55,24 +56,35 @@ const ( // Apart from basic data storage functionality it also supports batch writes and // iterating over the keyspace in binary-alphabetical order. type Database struct { - fn string // filename for reporting - db *pebble.DB // Underlying pebble storage engine - - compTimeMeter *metrics.Meter // Meter for measuring the total time spent in database compaction - compReadMeter *metrics.Meter // Meter for measuring the data read during compaction - compWriteMeter *metrics.Meter // Meter for measuring the data written during compaction - writeDelayNMeter *metrics.Meter // Meter for measuring the write delay number due to database compaction - writeDelayMeter *metrics.Meter // Meter for measuring the write delay duration due to database compaction - diskSizeGauge *metrics.Gauge // Gauge for tracking the size of all the levels in the database - diskReadMeter *metrics.Meter // Meter for measuring the effective amount of data read - diskWriteMeter *metrics.Meter // Meter for measuring the effective amount of data written - memCompGauge *metrics.Gauge // Gauge for tracking the number of memory compaction - level0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in level0 - nonlevel0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in non0 level - seekCompGauge *metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt - manualMemAllocGauge *metrics.Gauge // Gauge for tracking amount of non-managed memory currently allocated - - levelsGauge []*metrics.Gauge // Gauge for tracking the number of tables in levels + fn string // filename for reporting + db *pebble.DB // Underlying pebble storage engine + namespace string // Namespace for metrics + + compTimeMeter *metrics.Meter // Meter for measuring the total time spent in database compaction + compReadMeter *metrics.Meter // Meter for measuring the data read during compaction + compWriteMeter *metrics.Meter // Meter for measuring the data written during compaction + writeDelayNMeter *metrics.Meter // Meter for measuring the write delay number due to database compaction + writeDelayMeter *metrics.Meter // Meter for measuring the write delay duration due to database compaction + diskSizeGauge *metrics.Gauge // Gauge for tracking the size of all the levels in the database + diskReadMeter *metrics.Meter // Meter for measuring the effective amount of data read + diskWriteMeter *metrics.Meter // Meter for measuring the effective amount of data written + memCompGauge *metrics.Gauge // Gauge for tracking the number of memory compaction + level0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in level0 + nonlevel0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in non0 level + seekCompGauge *metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt + manualMemAllocGauge *metrics.Gauge // Gauge for tracking amount of non-managed memory currently allocated + liveMemTablesGauge *metrics.Gauge // Gauge for tracking the number of live memory tables + zombieMemTablesGauge *metrics.Gauge // Gauge for tracking the number of zombie memory tables + blockCacheHitGauge *metrics.Gauge // Gauge for tracking the number of total hit in the block cache + blockCacheMissGauge *metrics.Gauge // Gauge for tracking the number of total miss in the block cache + tableCacheHitGauge *metrics.Gauge // Gauge for tracking the number of total hit in the table cache + tableCacheMissGauge *metrics.Gauge // Gauge for tracking the number of total miss in the table cache + filterHitGauge *metrics.Gauge // Gauge for tracking the number of total hit in bloom filter + filterMissGauge *metrics.Gauge // Gauge for tracking the number of total miss in bloom filter + estimatedCompDebtGauge *metrics.Gauge // Gauge for tracking the number of bytes that need to be compacted + liveCompGauge *metrics.Gauge // Gauge for tracking the number of in-progress compactions + liveCompSizeGauge *metrics.Gauge // Gauge for tracking the size of in-progress compactions + levelsGauge []*metrics.Gauge // Gauge for tracking the number of tables in levels quitLock sync.RWMutex // Mutex protecting the quit channel and the closed flag quitChan chan chan error // Quit channel to stop the metrics collection before closing the database @@ -88,6 +100,7 @@ type Database struct { writeStalled atomic.Bool // Flag whether the write is stalled writeDelayStartTime time.Time // The start time of the latest write stall + writeDelayReason string // The reason of the latest write stall writeDelayCount atomic.Int64 // Total number of write stall counts writeDelayTime atomic.Int64 // Total time spent in write stalls @@ -120,11 +133,30 @@ func (d *Database) onWriteStallBegin(b pebble.WriteStallBeginInfo) { d.writeDelayStartTime = time.Now() d.writeDelayCount.Add(1) d.writeStalled.Store(true) + + // Take just the first word of the reason. These are two potential + // reasons for the write stall: + // - memtable count limit reached + // - L0 file count limit exceeded + reason := b.Reason + if i := strings.IndexByte(reason, ' '); i != -1 { + reason = reason[:i] + } + if reason == "L0" || reason == "memtable" { + d.writeDelayReason = reason + metrics.GetOrRegisterGauge(d.namespace+"stall/count/"+reason, nil).Inc(1) + } } func (d *Database) onWriteStallEnd() { d.writeDelayTime.Add(int64(time.Since(d.writeDelayStartTime))) d.writeStalled.Store(false) + + if d.writeDelayReason != "" { + metrics.GetOrRegisterResettingTimer(d.namespace+"stall/time/"+d.writeDelayReason, nil).UpdateSince(d.writeDelayStartTime) + d.writeDelayReason = "" + } + d.writeDelayStartTime = time.Time{} } // panicLogger is just a noop logger to disable Pebble's internal logger. @@ -270,6 +302,17 @@ func New(file string, cache int, handles int, namespace string, readonly bool) ( db.nonlevel0CompGauge = metrics.GetOrRegisterGauge(namespace+"compact/nonlevel0", nil) db.seekCompGauge = metrics.GetOrRegisterGauge(namespace+"compact/seek", nil) db.manualMemAllocGauge = metrics.GetOrRegisterGauge(namespace+"memory/manualalloc", nil) + db.liveMemTablesGauge = metrics.GetOrRegisterGauge(namespace+"table/live", nil) + db.zombieMemTablesGauge = metrics.GetOrRegisterGauge(namespace+"table/zombie", nil) + db.blockCacheHitGauge = metrics.GetOrRegisterGauge(namespace+"cache/block/hit", nil) + db.blockCacheMissGauge = metrics.GetOrRegisterGauge(namespace+"cache/block/miss", nil) + db.tableCacheHitGauge = metrics.GetOrRegisterGauge(namespace+"cache/table/hit", nil) + db.tableCacheMissGauge = metrics.GetOrRegisterGauge(namespace+"cache/table/miss", nil) + db.filterHitGauge = metrics.GetOrRegisterGauge(namespace+"filter/hit", nil) + db.filterMissGauge = metrics.GetOrRegisterGauge(namespace+"filter/miss", nil) + db.estimatedCompDebtGauge = metrics.GetOrRegisterGauge(namespace+"compact/estimateDebt", nil) + db.liveCompGauge = metrics.GetOrRegisterGauge(namespace+"compact/live/count", nil) + db.liveCompSizeGauge = metrics.GetOrRegisterGauge(namespace+"compact/live/size", nil) // Start up the metrics gathering and return go db.meter(metricsGatheringInterval, namespace) @@ -517,6 +560,18 @@ func (d *Database) meter(refresh time.Duration, namespace string) { d.nonlevel0CompGauge.Update(nonLevel0CompCount) d.level0CompGauge.Update(level0CompCount) d.seekCompGauge.Update(stats.Compact.ReadCount) + d.liveCompGauge.Update(stats.Compact.NumInProgress) + d.liveCompSizeGauge.Update(stats.Compact.InProgressBytes) + + d.liveMemTablesGauge.Update(stats.MemTable.Count) + d.zombieMemTablesGauge.Update(stats.MemTable.ZombieCount) + d.estimatedCompDebtGauge.Update(int64(stats.Compact.EstimatedDebt)) + d.tableCacheHitGauge.Update(stats.TableCache.Hits) + d.tableCacheMissGauge.Update(stats.TableCache.Misses) + d.blockCacheHitGauge.Update(stats.BlockCache.Hits) + d.blockCacheMissGauge.Update(stats.BlockCache.Misses) + d.filterHitGauge.Update(stats.Filter.Hits) + d.filterMissGauge.Update(stats.Filter.Misses) for i, level := range stats.Levels { // Append metrics for additional layers From d121c27acefb96b875f7d3047dd26e0b83862d59 Mon Sep 17 00:00:00 2001 From: Klimov Sergey Date: Mon, 12 May 2025 15:41:24 +0800 Subject: [PATCH 016/365] core/state: fix incorrect description of function behavior (#31809) --- core/state/statedb.go | 2 +- core/vm/interface.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 9378cae7de..2453d67f3e 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -298,7 +298,7 @@ func (s *StateDB) SubRefund(gas uint64) { } // Exist reports whether the given account address exists in the state. -// Notably this also returns true for self-destructed accounts. +// Notably this also returns true for self-destructed accounts within the current transaction. func (s *StateDB) Exist(addr common.Address) bool { return s.getStateObject(addr) != nil } diff --git a/core/vm/interface.go b/core/vm/interface.go index 57f35cb249..86e8c56ab0 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -69,7 +69,7 @@ type StateDB interface { SelfDestruct6780(common.Address) (uint256.Int, bool) // Exist reports whether the given account exists in state. - // Notably this should also return true for self-destructed accounts. + // Notably this also returns true for self-destructed accounts within the current transaction. Exist(common.Address) bool // Empty returns whether the given account is empty. Empty // is defined according to EIP161 (balance = nonce = code = 0). From c7bdf6b2fe4eae1db035147431147ed54f84fae7 Mon Sep 17 00:00:00 2001 From: SHADOW Date: Mon, 12 May 2025 15:01:48 +0530 Subject: [PATCH 017/365] accounts/abi/abigen: remove unnecessary test files (#31804) fix #31793: resolve conflict markers in structs-abi.go.txt --- .../abi/abigen/testdata/v2/structs-abi.go.txt | 116 ------------------ 1 file changed, 116 deletions(-) delete mode 100644 accounts/abi/abigen/testdata/v2/structs-abi.go.txt diff --git a/accounts/abi/abigen/testdata/v2/structs-abi.go.txt b/accounts/abi/abigen/testdata/v2/structs-abi.go.txt deleted file mode 100644 index aab6242707..0000000000 --- a/accounts/abi/abigen/testdata/v2/structs-abi.go.txt +++ /dev/null @@ -1,116 +0,0 @@ -// Code generated via abigen V2 - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package v1bindtests - -import ( - "bytes" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = bytes.Equal - _ = errors.New - _ = big.NewInt - _ = common.Big1 - _ = types.BloomLookup - _ = abi.ConvertType -) - -// Struct0 is an auto generated low-level Go binding around an user-defined struct. -type Struct0 struct { - B [32]byte -} - -// StructsMetaData contains all meta data concerning the Structs contract. -var StructsMetaData = bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"F\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[]\",\"name\":\"c\",\"type\":\"uint256[]\"},{\"internalType\":\"bool[]\",\"name\":\"d\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"G\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - ID: "Structs", -} - -// Structs is an auto generated Go binding around an Ethereum contract. -type Structs struct { - abi abi.ABI -} - -// NewStructs creates a new instance of Structs. -func NewStructs() *Structs { - parsed, err := StructsMetaData.ParseABI() - if err != nil { - panic(errors.New("invalid ABI: " + err.Error())) - } - return &Structs{abi: *parsed} -} - -// Instance creates a wrapper for a deployed contract instance at the given address. -<<<<<<< HEAD -// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc. -func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract { - return bind.NewBoundContract(addr, c.abi, backend, backend, backend) -======= -// Use this to create the instance object passed to abigen v2 library functions Call, -// Transact, etc. -func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) bind.BoundContract { - return bind.NewBoundContract(backend, addr, c.abi) ->>>>>>> 854c25e086 (accounts/abi/abigen: improve v2 template) -} - -// F is the Go binding used to pack the parameters required for calling -// the contract method 0x28811f59. -// -// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d) -func (structs *Structs) PackF() ([]byte, error) { - return structs.abi.Pack("F") -} - -// FOutput serves as a container for the return parameters of contract -// method F. -type FOutput struct { - A []Struct0 - C []*big.Int - D []bool -} - -// UnpackF is the Go binding that unpacks the parameters returned -// from invoking the contract method with ID 0x28811f59. -// -// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d) -func (structs *Structs) UnpackF(data []byte) (*FOutput, error) { - out, err := structs.abi.Unpack("F", data) - if err != nil { - return nil, err - } - ret := new(FOutput) - ret.A = *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0) - ret.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int) - ret.D = *abi.ConvertType(out[2], new([]bool)).(*[]bool) - return ret, nil -} - -// G is the Go binding used to pack the parameters required for calling -// the contract method 0x6fecb623. -// -// Solidity: function G() view returns((bytes32)[] a) -func (structs *Structs) PackG() ([]byte, error) { - return structs.abi.Pack("G") -} - -// UnpackG is the Go binding that unpacks the parameters returned -// from invoking the contract method with ID 0x6fecb623. -// -// Solidity: function G() view returns((bytes32)[] a) -func (structs *Structs) UnpackG(data []byte) (*[]Struct0, error) { - out, err := structs.abi.Unpack("G", data) - if err != nil { - return nil, err - } - out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0) - return &out0, nil -} From 2cd5f22037f1c148a536b0d9b766365519c9cf60 Mon Sep 17 00:00:00 2001 From: wellna Date: Tue, 13 May 2025 13:11:27 +0100 Subject: [PATCH 018/365] crypto/kzg4844: use package github.com/crate-crypto/go-eth-kzg (#31806) I saw in https://github.com/ethereum/go-ethereum/pull/31378 introduced github.com/crate-crypto/go-eth-kzg to calculate the kzg hash, and github.com/crate-crypto/go-kzg-4844 was only used in the test files, so propose to drop it with go-eth-kzg instead --- crypto/kzg4844/kzg4844_test.go | 2 +- go.mod | 1 - go.sum | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/crypto/kzg4844/kzg4844_test.go b/crypto/kzg4844/kzg4844_test.go index a6782d4768..7fa261e523 100644 --- a/crypto/kzg4844/kzg4844_test.go +++ b/crypto/kzg4844/kzg4844_test.go @@ -21,7 +21,7 @@ import ( "testing" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" - gokzg4844 "github.com/crate-crypto/go-kzg-4844" + gokzg4844 "github.com/crate-crypto/go-eth-kzg" ) func randFieldElement() [32]byte { diff --git a/go.mod b/go.mod index 924f0d2642..d27af647ec 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/consensys/gnark-crypto v0.16.0 github.com/crate-crypto/go-eth-kzg v1.3.0 github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a - github.com/crate-crypto/go-kzg-4844 v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.6.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 diff --git a/go.sum b/go.sum index 5d35a7a0e1..200b3725ea 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,6 @@ github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= -github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= -github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= From c53db5e1f6383606d6de2fc4577ed7dbc6f8def4 Mon Sep 17 00:00:00 2001 From: maskpp Date: Tue, 13 May 2025 21:28:16 +0800 Subject: [PATCH 019/365] eth: fix returned blockContext for empty blocks in stateAtTransaction (#31768) Co-authored-by: lightclient --- eth/state_accessor.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 99ed28d96a..3c3e79a584 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -217,7 +217,13 @@ func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexe return eth.pathState(block) } -// stateAtTransaction returns the execution environment of a certain transaction. +// stateAtTransaction returns the execution environment of a certain +// transaction. +// +// Note: when a block is empty and the state for tx index 0 is requested, this +// function will return the state of block after the pre-block operations have +// been completed (e.g. updating system contracts), but before post-block +// operations are completed (e.g. processing withdrawals). func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { // Short circuit if it's genesis block. if block.NumberU64() == 0 { @@ -245,7 +251,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, core.ProcessParentBlockHash(block.ParentHash(), evm) } if txIndex == 0 && len(block.Transactions()) == 0 { - return nil, vm.BlockContext{}, statedb, release, nil + return nil, context, statedb, release, nil } // Recompute transactions up to the target index. signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time()) From 88a7ef233abcddca1da79c88ab78a1243e23837d Mon Sep 17 00:00:00 2001 From: Delweng Date: Wed, 14 May 2025 09:26:08 +0800 Subject: [PATCH 020/365] core: use unix time to check fork readiness (#31800) --- core/blockchain.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 302ab14cf0..320b90dcbe 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2543,14 +2543,22 @@ func (bc *BlockChain) reportBlock(block *types.Block, res *ProcessResult, err er // logForkReadiness will write a log when a future fork is scheduled, but not // active. This is useful so operators know their client is ready for the fork. func (bc *BlockChain) logForkReadiness(block *types.Block) { - c := bc.Config() - current, last := c.LatestFork(block.Time()), c.LatestFork(math.MaxUint64) - t := c.Timestamp(last) - if t == nil { + config := bc.Config() + current, last := config.LatestFork(block.Time()), config.LatestFork(math.MaxUint64) + + // Short circuit if the timestamp of the last fork is undefined, + // or if the network has already passed the last configured fork. + t := config.Timestamp(last) + if t == nil || current >= last { return } at := time.Unix(int64(*t), 0) - if current < last && time.Now().After(bc.lastForkReadyAlert.Add(forkReadyInterval)) { + + // Only log if: + // - Current time is before the fork activation time + // - Enough time has passed since last alert + now := time.Now() + if now.Before(at) && now.After(bc.lastForkReadyAlert.Add(forkReadyInterval)) { log.Info("Ready for fork activation", "fork", last, "date", at.Format(time.RFC822), "remaining", time.Until(at).Round(time.Second), "timestamp", at.Unix()) bc.lastForkReadyAlert = time.Now() From 16b0d9e982f7f0469930b59ba62d0c9e43281b78 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Wed, 14 May 2025 16:50:02 +0200 Subject: [PATCH 021/365] eth/catalyst: refactor engine api checks (#31182) This PR contains three refactors: - refactor the latest fork check that we use quite extensively - refactor the nil checks in NewPayloads --------- Co-authored-by: lightclient --- eth/catalyst/api.go | 449 +++++++++++++++++++++----------------------- 1 file changed, 217 insertions(+), 232 deletions(-) diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 1e6981a76a..be25712c97 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -38,6 +38,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params/forks" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" @@ -196,11 +197,11 @@ func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI { // and return its payloadID. func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { if payloadAttributes != nil { - if payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals and beacon root not supported in V1")) - } - if api.eth.BlockChain().Config().IsShanghai(api.eth.BlockChain().Config().LondonBlock, payloadAttributes.Timestamp) { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai")) + switch { + case payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil: + return engine.STATUS_INVALID, paramsErr("withdrawals and beacon root not supported in V1") + case !api.checkFork(payloadAttributes.Timestamp, forks.Paris, forks.Shanghai): + return engine.STATUS_INVALID, paramsErr("fcuV1 called post-shanghai") } } return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, false) @@ -210,20 +211,15 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa // attributes. It supports both PayloadAttributesV1 and PayloadAttributesV2. func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { if params != nil { - if params.BeaconRoot != nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("unexpected beacon root")) - } - switch api.eth.BlockChain().Config().LatestFork(params.Timestamp) { - case forks.Paris: - if params.Withdrawals != nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai")) - } - case forks.Shanghai: - if params.Withdrawals == nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing withdrawals")) - } - default: - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called with paris and shanghai payloads")) + switch { + case params.BeaconRoot != nil: + return engine.STATUS_INVALID, attributesErr("unexpected beacon root") + case api.checkFork(params.Timestamp, forks.Paris) && params.Withdrawals != nil: + return engine.STATUS_INVALID, attributesErr("withdrawals before shanghai") + case api.checkFork(params.Timestamp, forks.Shanghai) && params.Withdrawals == nil: + return engine.STATUS_INVALID, attributesErr("missing withdrawals") + case !api.checkFork(params.Timestamp, forks.Paris, forks.Shanghai): + return engine.STATUS_INVALID, unsupportedForkErr("fcuV2 must only be called with paris or shanghai payloads") } } return api.forkchoiceUpdated(update, params, engine.PayloadV2, false) @@ -233,14 +229,13 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa // in the payload attributes. It supports only PayloadAttributesV3. func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { if params != nil { - if params.Withdrawals == nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing withdrawals")) - } - if params.BeaconRoot == nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root")) - } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads")) + switch { + case params.Withdrawals == nil: + return engine.STATUS_INVALID, attributesErr("missing withdrawals") + case params.BeaconRoot == nil: + return engine.STATUS_INVALID, attributesErr("missing beacon root") + case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague): + return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads") } } // TODO(matt): the spec requires that fcu is applied when called on a valid @@ -254,11 +249,11 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa // generates an execution witness too if block building was requested. func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { if payloadAttributes != nil { - if payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals and beacon root not supported in V1")) - } - if api.eth.BlockChain().Config().IsShanghai(api.eth.BlockChain().Config().LondonBlock, payloadAttributes.Timestamp) { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai")) + switch { + case payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil: + return engine.STATUS_INVALID, paramsErr("withdrawals and beacon root not supported in V1") + case !api.checkFork(payloadAttributes.Timestamp, forks.Paris, forks.Shanghai): + return engine.STATUS_INVALID, paramsErr("fcuV1 called post-shanghai") } } return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, true) @@ -268,20 +263,15 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(update engine.Forkchoice // generates an execution witness too if block building was requested. func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { if params != nil { - if params.BeaconRoot != nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("unexpected beacon root")) - } - switch api.eth.BlockChain().Config().LatestFork(params.Timestamp) { - case forks.Paris: - if params.Withdrawals != nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai")) - } - case forks.Shanghai: - if params.Withdrawals == nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing withdrawals")) - } - default: - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called with paris and shanghai payloads")) + switch { + case params.BeaconRoot != nil: + return engine.STATUS_INVALID, attributesErr("unexpected beacon root") + case api.checkFork(params.Timestamp, forks.Paris) && params.Withdrawals != nil: + return engine.STATUS_INVALID, attributesErr("withdrawals before shanghai") + case api.checkFork(params.Timestamp, forks.Shanghai) && params.Withdrawals == nil: + return engine.STATUS_INVALID, attributesErr("missing withdrawals") + case !api.checkFork(params.Timestamp, forks.Paris, forks.Shanghai): + return engine.STATUS_INVALID, unsupportedForkErr("fcuV2 must only be called with paris or shanghai payloads") } } return api.forkchoiceUpdated(update, params, engine.PayloadV2, true) @@ -291,14 +281,13 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(update engine.Forkchoice // generates an execution witness too if block building was requested. func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { if params != nil { - if params.Withdrawals == nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing withdrawals")) - } - if params.BeaconRoot == nil { - return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root")) - } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads")) + switch { + case params.Withdrawals == nil: + return engine.STATUS_INVALID, attributesErr("missing withdrawals") + case params.BeaconRoot == nil: + return engine.STATUS_INVALID, attributesErr("missing beacon root") + case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague): + return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads") } } // TODO(matt): the spec requires that fcu is applied when called on a valid @@ -468,7 +457,7 @@ func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.Transit api.lastTransitionUpdate = time.Now() api.lastTransitionLock.Unlock() - ttd := api.eth.BlockChain().Config().TerminalTotalDifficulty + ttd := api.config().TerminalTotalDifficulty if ttd == nil || ttd.Cmp(config.TerminalTotalDifficulty.ToInt()) != 0 { log.Warn("Invalid TTD configured", "geth", ttd, "beacon", config.TerminalTotalDifficulty) return nil, fmt.Errorf("invalid ttd: execution %v consensus %v", ttd, config.TerminalTotalDifficulty) @@ -550,86 +539,74 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo return res, nil } +// Helper for NewPayload* methods. +var invalidStatus = engine.PayloadStatusV1{Status: engine.INVALID} + // NewPayloadV1 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) { if params.Withdrawals != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) + return invalidStatus, paramsErr("withdrawals not supported in V1") } return api.newPayload(params, nil, nil, nil, false) } // NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun")) - } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - } else { - if params.Withdrawals != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai")) - } - } - if params.ExcessBlobGas != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil excessBlobGas pre-cancun")) - } - if params.BlobGasUsed != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil blobGasUsed pre-cancun")) + var ( + cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp) + shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp) + ) + switch { + case cancun: + return invalidStatus, paramsErr("can't use newPayloadV2 post-cancun") + case shanghai && params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case !shanghai && params.Withdrawals != nil: + return invalidStatus, paramsErr("non-nil withdrawals pre-shanghai") + case params.ExcessBlobGas != nil: + return invalidStatus, paramsErr("non-nil excessBlobGas pre-cancun") + case params.BlobGasUsed != nil: + return invalidStatus, paramsErr("non-nil blobGasUsed pre-cancun") } return api.newPayload(params, nil, nil, nil, false) } // NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - if params.ExcessBlobGas == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) - } - if params.BlobGasUsed == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) - } - - if versionedHashes == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) - } - if beaconRoot == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) - } - - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads")) + switch { + case params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return invalidStatus, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return invalidStatus, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return invalidStatus, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return invalidStatus, paramsErr("nil beaconRoot post-cancun") + case !api.checkFork(params.Timestamp, forks.Cancun): + return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") } return api.newPayload(params, versionedHashes, beaconRoot, nil, false) } // NewPayloadV4 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - if params.ExcessBlobGas == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) - } - if params.BlobGasUsed == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) - } - - if versionedHashes == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) - } - if beaconRoot == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) - } - if executionRequests == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague")) - } - - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV4 must only be called for prague payloads")) + switch { + case params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return invalidStatus, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return invalidStatus, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return invalidStatus, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return invalidStatus, paramsErr("nil beaconRoot post-cancun") + case executionRequests == nil: + return invalidStatus, paramsErr("nil executionRequests post-prague") + case !api.checkFork(params.Timestamp, forks.Prague): + return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") } requests := convertRequests(executionRequests) if err := validateRequests(requests); err != nil { @@ -650,23 +627,21 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV1(params engine.ExecutableData) ( // NewPayloadWithWitnessV2 is analogous to NewPayloadV2, only it also generates // and returns a stateless witness after running the payload. func (api *ConsensusAPI) NewPayloadWithWitnessV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun")) - } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - } else { - if params.Withdrawals != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai")) - } - } - if params.ExcessBlobGas != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil excessBlobGas pre-cancun")) - } - if params.BlobGasUsed != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil blobGasUsed pre-cancun")) + var ( + cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp) + shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp) + ) + switch { + case cancun: + return invalidStatus, paramsErr("can't use newPayloadV2 post-cancun") + case shanghai && params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case !shanghai && params.Withdrawals != nil: + return invalidStatus, paramsErr("non-nil withdrawals pre-shanghai") + case params.ExcessBlobGas != nil: + return invalidStatus, paramsErr("non-nil excessBlobGas pre-cancun") + case params.BlobGasUsed != nil: + return invalidStatus, paramsErr("non-nil blobGasUsed pre-cancun") } return api.newPayload(params, nil, nil, nil, true) } @@ -674,25 +649,19 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV2(params engine.ExecutableData) ( // NewPayloadWithWitnessV3 is analogous to NewPayloadV3, only it also generates // and returns a stateless witness after running the payload. func (api *ConsensusAPI) NewPayloadWithWitnessV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - if params.ExcessBlobGas == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) - } - if params.BlobGasUsed == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) - } - - if versionedHashes == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) - } - if beaconRoot == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) - } - - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadWithWitnessV3 must only be called for cancun payloads")) + switch { + case params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return invalidStatus, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return invalidStatus, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return invalidStatus, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return invalidStatus, paramsErr("nil beaconRoot post-cancun") + case !api.checkFork(params.Timestamp, forks.Cancun): + return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") } return api.newPayload(params, versionedHashes, beaconRoot, nil, true) } @@ -700,28 +669,21 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV3(params engine.ExecutableData, v // NewPayloadWithWitnessV4 is analogous to NewPayloadV4, only it also generates // and returns a stateless witness after running the payload. func (api *ConsensusAPI) NewPayloadWithWitnessV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - if params.ExcessBlobGas == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) - } - if params.BlobGasUsed == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) - } - - if versionedHashes == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) - } - if beaconRoot == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) - } - if executionRequests == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague")) - } - - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadWithWitnessV4 must only be called for prague payloads")) + switch { + case params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return invalidStatus, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return invalidStatus, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return invalidStatus, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return invalidStatus, paramsErr("nil beaconRoot post-cancun") + case executionRequests == nil: + return invalidStatus, paramsErr("nil executionRequests post-prague") + case !api.checkFork(params.Timestamp, forks.Prague): + return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") } requests := convertRequests(executionRequests) if err := validateRequests(requests); err != nil { @@ -742,23 +704,21 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV1(params engine.ExecutableData, // ExecuteStatelessPayloadV2 is analogous to NewPayloadV2, only it operates in // a stateless mode on top of a provided witness instead of the local database. func (api *ConsensusAPI) ExecuteStatelessPayloadV2(params engine.ExecutableData, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun")) - } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai { - if params.Withdrawals == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - } else { - if params.Withdrawals != nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai")) - } - } - if params.ExcessBlobGas != nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil excessBlobGas pre-cancun")) - } - if params.BlobGasUsed != nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil blobGasUsed pre-cancun")) + var ( + cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp) + shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp) + ) + switch { + case cancun: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("can't use newPayloadV2 post-cancun") + case shanghai && params.Withdrawals == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") + case !shanghai && params.Withdrawals != nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil withdrawals pre-shanghai") + case params.ExcessBlobGas != nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil excessBlobGas pre-cancun") + case params.BlobGasUsed != nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil blobGasUsed pre-cancun") } return api.executeStatelessPayload(params, nil, nil, nil, opaqueWitness) } @@ -766,25 +726,19 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV2(params engine.ExecutableData, // ExecuteStatelessPayloadV3 is analogous to NewPayloadV3, only it operates in // a stateless mode on top of a provided witness instead of the local database. func (api *ConsensusAPI) ExecuteStatelessPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - if params.Withdrawals == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - if params.ExcessBlobGas == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) - } - if params.BlobGasUsed == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) - } - - if versionedHashes == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) - } - if beaconRoot == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) - } - - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("executeStatelessPayloadV3 must only be called for cancun payloads")) + switch { + case params.Withdrawals == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun") + case !api.checkFork(params.Timestamp, forks.Cancun): + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") } return api.executeStatelessPayload(params, versionedHashes, beaconRoot, nil, opaqueWitness) } @@ -792,30 +746,26 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV3(params engine.ExecutableData, // ExecuteStatelessPayloadV4 is analogous to NewPayloadV4, only it operates in // a stateless mode on top of a provided witness instead of the local database. func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - if params.Withdrawals == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - if params.ExcessBlobGas == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) - } - if params.BlobGasUsed == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) - } - - if versionedHashes == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) - } - if beaconRoot == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) - } - if executionRequests == nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague")) - } - - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("executeStatelessPayloadV4 must only be called for prague payloads")) + switch { + case params.Withdrawals == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun") + case executionRequests == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague") + case !api.checkFork(params.Timestamp, forks.Prague): + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") } requests := convertRequests(executionRequests) + if err := validateRequests(requests); err != nil { + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err) + } return api.executeStatelessPayload(params, versionedHashes, beaconRoot, requests, opaqueWitness) } @@ -981,7 +931,7 @@ func (api *ConsensusAPI) executeStatelessPayload(params engine.ExecutableData, v api.lastNewPayloadLock.Unlock() log.Trace("Executing block statelessly", "number", block.Number(), "hash", params.BlockHash) - stateRoot, receiptRoot, err := core.ExecuteStateless(api.eth.BlockChain().Config(), vm.Config{}, block, witness) + stateRoot, receiptRoot, err := core.ExecuteStateless(api.config(), vm.Config{}, block, witness) if err != nil { log.Warn("ExecuteStatelessPayload: execution failed", "err", err) errorMsg := err.Error() @@ -1119,7 +1069,7 @@ func (api *ConsensusAPI) heartbeat() { time.Sleep(beaconUpdateStartupTimeout) // If the network is not yet merged/merging, don't bother continuing. - if api.eth.BlockChain().Config().TerminalTotalDifficulty == nil { + if api.config().TerminalTotalDifficulty == nil { return } @@ -1163,6 +1113,23 @@ func (api *ConsensusAPI) heartbeat() { } } +// config retrieves the chain's fork configuration. +func (api *ConsensusAPI) config() *params.ChainConfig { + return api.eth.BlockChain().Config() +} + +// checkFork returns true if the latest fork at the given timestamp +// is one of the forks provided. +func (api *ConsensusAPI) checkFork(timestamp uint64, forks ...forks.Fork) bool { + latest := api.config().LatestFork(timestamp) + for _, fork := range forks { + if latest == fork { + return true + } + } + return false +} + // ExchangeCapabilities returns the current methods provided by this node. func (api *ConsensusAPI) ExchangeCapabilities([]string) []string { return caps @@ -1288,3 +1255,21 @@ func validateRequests(requests [][]byte) error { } return nil } + +// paramsErr is a helper function for creating an InvalidPayloadAttributes +// Engine API error. +func paramsErr(msg string) error { + return engine.InvalidParams.With(errors.New(msg)) +} + +// attributesErr is a helper function for creating an InvalidPayloadAttributes +// Engine API error. +func attributesErr(msg string) error { + return engine.InvalidPayloadAttributes.With(errors.New(msg)) +} + +// unsupportedForkErr is a helper function for creating an UnsupportedFork +// Engine API error. +func unsupportedForkErr(msg string) error { + return engine.UnsupportedFork.With(errors.New(msg)) +} From 52dbd206bb9ea9b4a1f0f7feaefc5f7828dd4c67 Mon Sep 17 00:00:00 2001 From: maskpp Date: Thu, 15 May 2025 15:32:20 +0800 Subject: [PATCH 022/365] cmd/utils: always record preimages in dev mode (#31821) Fix a todo: force-enable this in --dev mode --------- Co-authored-by: jwasinger --- cmd/utils/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 44363d13f4..a100ee1548 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1712,7 +1712,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } } if ctx.IsSet(VMEnableDebugFlag.Name) { - // TODO(fjl): force-enable this in --dev mode cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) } @@ -1761,6 +1760,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { case ctx.Bool(DeveloperFlag.Name): cfg.NetworkId = 1337 cfg.SyncMode = ethconfig.FullSync + cfg.EnablePreimageRecording = true // Create new developer account or reuse existing one var ( developer accounts.Account From 228803c1a29acf93c8cd53a29e477d8801fc60ad Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 15 May 2025 14:17:58 +0200 Subject: [PATCH 023/365] p2p/enode: add support for naming iterator sources (#31779) This adds support for naming the source iterators of FairMix, like so: mix.AddSource(enode.WithSourceName("mySource", iter)) The source that produced the latest node is returned by the new NodeSource method. --- p2p/enode/iter.go | 79 ++++++++++++++++++++++++++++++++---------- p2p/enode/iter_test.go | 48 +++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 18 deletions(-) diff --git a/p2p/enode/iter.go b/p2p/enode/iter.go index b8ab4a758a..4b7e28929e 100644 --- a/p2p/enode/iter.go +++ b/p2p/enode/iter.go @@ -30,6 +30,35 @@ type Iterator interface { Close() // ends the iterator } +// SourceIterator represents a sequence of nodes like [Iterator] +// Each node also has a named 'source'. +type SourceIterator interface { + Iterator + NodeSource() string // source of current node +} + +// WithSource attaches a 'source name' to an iterator. +func WithSourceName(name string, it Iterator) SourceIterator { + return sourceIter{it, name} +} + +func ensureSourceIter(it Iterator) SourceIterator { + if si, ok := it.(SourceIterator); ok { + return si + } + return WithSourceName("", it) +} + +type sourceIter struct { + Iterator + name string +} + +// NodeSource implements IteratorSource. +func (it sourceIter) NodeSource() string { + return it.name +} + // ReadNodes reads at most n nodes from the given iterator. The return value contains no // duplicates and no nil values. To prevent looping indefinitely for small repeating node // sequences, this function calls Next at most n times. @@ -106,16 +135,16 @@ func (it *sliceIter) Close() { // Filter wraps an iterator such that Next only returns nodes for which // the 'check' function returns true. func Filter(it Iterator, check func(*Node) bool) Iterator { - return &filterIter{it, check} + return &filterIter{ensureSourceIter(it), check} } type filterIter struct { - Iterator + SourceIterator check func(*Node) bool } func (f *filterIter) Next() bool { - for f.Iterator.Next() { + for f.SourceIterator.Next() { if f.check(f.Node()) { return true } @@ -135,9 +164,9 @@ func (f *filterIter) Next() bool { // It's safe to call AddSource and Close concurrently with Next. type FairMix struct { wg sync.WaitGroup - fromAny chan *Node + fromAny chan mixItem timeout time.Duration - cur *Node + cur mixItem mu sync.Mutex closed chan struct{} @@ -146,11 +175,16 @@ type FairMix struct { } type mixSource struct { - it Iterator - next chan *Node + it SourceIterator + next chan mixItem timeout time.Duration } +type mixItem struct { + n *Node + source string +} + // NewFairMix creates a mixer. // // The timeout specifies how long the mixer will wait for the next fairly-chosen source @@ -159,7 +193,7 @@ type mixSource struct { // timeout makes the mixer completely fair. func NewFairMix(timeout time.Duration) *FairMix { m := &FairMix{ - fromAny: make(chan *Node), + fromAny: make(chan mixItem), closed: make(chan struct{}), timeout: timeout, } @@ -175,7 +209,11 @@ func (m *FairMix) AddSource(it Iterator) { return } m.wg.Add(1) - source := &mixSource{it, make(chan *Node), m.timeout} + source := &mixSource{ + it: ensureSourceIter(it), + next: make(chan mixItem), + timeout: m.timeout, + } m.sources = append(m.sources, source) go m.runSource(m.closed, source) } @@ -201,7 +239,7 @@ func (m *FairMix) Close() { // Next returns a node from a random source. func (m *FairMix) Next() bool { - m.cur = nil + m.cur = mixItem{} for { source := m.pickSource() @@ -217,12 +255,12 @@ func (m *FairMix) Next() bool { } select { - case n, ok := <-source.next: + case item, ok := <-source.next: if ok { // Here, the timeout is reset to the configured value // because the source delivered a node. source.timeout = m.timeout - m.cur = n + m.cur = item return true } // This source has ended. @@ -239,15 +277,20 @@ func (m *FairMix) Next() bool { // Node returns the current node. func (m *FairMix) Node() *Node { - return m.cur + return m.cur.n +} + +// NodeSource returns the current node's source name. +func (m *FairMix) NodeSource() string { + return m.cur.source } // nextFromAny is used when there are no sources or when the 'fair' choice // doesn't turn up a node quickly enough. func (m *FairMix) nextFromAny() bool { - n, ok := <-m.fromAny + item, ok := <-m.fromAny if ok { - m.cur = n + m.cur = item } return ok } @@ -284,10 +327,10 @@ func (m *FairMix) runSource(closed chan struct{}, s *mixSource) { defer m.wg.Done() defer close(s.next) for s.it.Next() { - n := s.it.Node() + item := mixItem{s.it.Node(), s.it.NodeSource()} select { - case s.next <- n: - case m.fromAny <- n: + case s.next <- item: + case m.fromAny <- item: case <-closed: return } diff --git a/p2p/enode/iter_test.go b/p2p/enode/iter_test.go index b736ed450a..577f9c2825 100644 --- a/p2p/enode/iter_test.go +++ b/p2p/enode/iter_test.go @@ -19,6 +19,7 @@ package enode import ( "encoding/binary" "runtime" + "slices" "sync/atomic" "testing" "time" @@ -183,6 +184,53 @@ func TestFairMixRemoveSource(t *testing.T) { } } +// This checks that FairMix correctly returns the name of the source that produced the node. +func TestFairMixSourceName(t *testing.T) { + nodes := make([]*Node, 6) + for i := range nodes { + nodes[i] = testNode(uint64(i), uint64(i)) + } + mix := NewFairMix(-1) + mix.AddSource(WithSourceName("s1", IterNodes(nodes[0:2]))) + mix.AddSource(WithSourceName("s2", IterNodes(nodes[2:4]))) + mix.AddSource(WithSourceName("s3", IterNodes(nodes[4:6]))) + + var names []string + for range nodes { + mix.Next() + names = append(names, mix.NodeSource()) + } + want := []string{"s2", "s3", "s1", "s2", "s3", "s1"} + if !slices.Equal(names, want) { + t.Fatalf("wrong names: %v", names) + } +} + +// This checks that FairMix returns the name of the source that produced the node, +// even when FairMix instances are nested. +func TestFairMixNestedSourceName(t *testing.T) { + nodes := make([]*Node, 6) + for i := range nodes { + nodes[i] = testNode(uint64(i), uint64(i)) + } + mix := NewFairMix(-1) + mix.AddSource(WithSourceName("s1", IterNodes(nodes[0:2]))) + submix := NewFairMix(-1) + submix.AddSource(WithSourceName("s2", IterNodes(nodes[2:4]))) + submix.AddSource(WithSourceName("s3", IterNodes(nodes[4:6]))) + mix.AddSource(submix) + + var names []string + for range nodes { + mix.Next() + names = append(names, mix.NodeSource()) + } + want := []string{"s3", "s1", "s2", "s1", "s3", "s2"} + if !slices.Equal(names, want) { + t.Fatalf("wrong names: %v", names) + } +} + type blockingIter chan struct{} func (it blockingIter) Next() bool { From af9a3a1a03d5155494a54b7b450333d70641e38a Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Thu, 15 May 2025 14:43:52 +0200 Subject: [PATCH 024/365] core/state, core/vm: update stateless gas costs to follow the verkle-gen-7 testnet (#31014) Adding values to the witness introduces a new class of issues for computing gas: if there is not enough gas to cover adding an item to the witness, then the item should not be added to the witness. The problem happens when several items are added together, and that process runs out of gas. The witness gas computation needs a way to signal that not enough gas was provided. These values can not be hardcoded, however, as they are context dependent, i.e. two calls to the same function with the same parameters can give two different results. The approach is to return both the gas that was actually consumed, and the gas that was necessary. If the values don't match, then a witness update OOG'd. The caller should then charge the `consumed` value (remaining gas will be 0) and error out. Why not return a boolean instead of the wanted value? Because when several items are touched, we want to distinguish which item lacked gas. --------- Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> --- core/state/access_events.go | 187 +++++++++++++++++++------------ core/state/access_events_test.go | 33 +++--- core/state_transition.go | 4 +- core/vm/contracts.go | 2 +- core/vm/eips.go | 22 ++-- core/vm/evm.go | 24 ++-- core/vm/gas_table.go | 19 +--- core/vm/interpreter.go | 6 +- core/vm/jump_table.go | 2 +- core/vm/operations_verkle.go | 178 +++++++++++++++++------------ 10 files changed, 275 insertions(+), 202 deletions(-) diff --git a/core/state/access_events.go b/core/state/access_events.go index b745c383b1..0575c9898a 100644 --- a/core/state/access_events.go +++ b/core/state/access_events.go @@ -18,6 +18,7 @@ package state import ( "maps" + gomath "math" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" @@ -92,97 +93,94 @@ func (ae *AccessEvents) Copy() *AccessEvents { // AddAccount returns the gas to be charged for each of the currently cold // member fields of an account. -func (ae *AccessEvents) AddAccount(addr common.Address, isWrite bool) uint64 { - var gas uint64 - gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, isWrite) - gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, isWrite) +func (ae *AccessEvents) AddAccount(addr common.Address, isWrite bool, availableGas uint64) uint64 { + var gas uint64 // accumulate the consumed gas + consumed, expected := ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, isWrite, availableGas) + if consumed < expected { + return expected + } + gas += consumed + consumed, expected = ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, isWrite, availableGas-consumed) + if consumed < expected { + return expected + gas + } + gas += expected return gas } // MessageCallGas returns the gas to be charged for each of the currently // cold member fields of an account, that need to be touched when making a message // call to that account. -func (ae *AccessEvents) MessageCallGas(destination common.Address) uint64 { - var gas uint64 - gas += ae.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.BasicDataLeafKey, false) - return gas +func (ae *AccessEvents) MessageCallGas(destination common.Address, availableGas uint64) uint64 { + _, expected := ae.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.BasicDataLeafKey, false, availableGas) + if expected == 0 { + expected = params.WarmStorageReadCostEIP2929 + } + return expected } // ValueTransferGas returns the gas to be charged for each of the currently // cold balance member fields of the caller and the callee accounts. -func (ae *AccessEvents) ValueTransferGas(callerAddr, targetAddr common.Address) uint64 { - var gas uint64 - gas += ae.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BasicDataLeafKey, true) - gas += ae.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true) - return gas +func (ae *AccessEvents) ValueTransferGas(callerAddr, targetAddr common.Address, availableGas uint64) uint64 { + _, expected1 := ae.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, availableGas) + if expected1 > availableGas { + return expected1 + } + _, expected2 := ae.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, availableGas-expected1) + if expected1+expected2 == 0 { + return params.WarmStorageReadCostEIP2929 + } + return expected1 + expected2 } // ContractCreatePreCheckGas charges access costs before // a contract creation is initiated. It is just reads, because the // address collision is done before the transfer, and so no write // are guaranteed to happen at this point. -func (ae *AccessEvents) ContractCreatePreCheckGas(addr common.Address) uint64 { - var gas uint64 - gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, false) - gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, false) - return gas +func (ae *AccessEvents) ContractCreatePreCheckGas(addr common.Address, availableGas uint64) uint64 { + consumed, expected1 := ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, false, availableGas) + _, expected2 := ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, false, availableGas-consumed) + return expected1 + expected2 } // ContractCreateInitGas returns the access gas costs for the initialization of // a contract creation. -func (ae *AccessEvents) ContractCreateInitGas(addr common.Address) uint64 { +func (ae *AccessEvents) ContractCreateInitGas(addr common.Address, availableGas uint64) (uint64, uint64) { var gas uint64 - gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, true) - gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, true) - return gas + consumed, expected1 := ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, true, availableGas) + gas += consumed + consumed, expected2 := ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, true, availableGas-consumed) + gas += consumed + return gas, expected1 + expected2 } // AddTxOrigin adds the member fields of the sender account to the access event list, // so that cold accesses are not charged, since they are covered by the 21000 gas. func (ae *AccessEvents) AddTxOrigin(originAddr common.Address) { - ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.BasicDataLeafKey, true) - ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.CodeHashLeafKey, false) + ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, gomath.MaxUint64) + ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.CodeHashLeafKey, false, gomath.MaxUint64) } // AddTxDestination adds the member fields of the sender account to the access event list, // so that cold accesses are not charged, since they are covered by the 21000 gas. -func (ae *AccessEvents) AddTxDestination(addr common.Address, sendsValue bool) { - ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, sendsValue) - ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, false) +func (ae *AccessEvents) AddTxDestination(addr common.Address, sendsValue, doesntExist bool) { + ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, sendsValue, gomath.MaxUint64) + ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, doesntExist, gomath.MaxUint64) } // SlotGas returns the amount of gas to be charged for a cold storage access. -func (ae *AccessEvents) SlotGas(addr common.Address, slot common.Hash, isWrite bool) uint64 { +func (ae *AccessEvents) SlotGas(addr common.Address, slot common.Hash, isWrite bool, availableGas uint64, chargeWarmCosts bool) uint64 { treeIndex, subIndex := utils.StorageIndex(slot.Bytes()) - return ae.touchAddressAndChargeGas(addr, *treeIndex, subIndex, isWrite) -} - -// touchAddressAndChargeGas adds any missing access event to the access event list, and returns the cold -// access cost to be charged, if need be. -func (ae *AccessEvents) touchAddressAndChargeGas(addr common.Address, treeIndex uint256.Int, subIndex byte, isWrite bool) uint64 { - stemRead, selectorRead, stemWrite, selectorWrite, selectorFill := ae.touchAddress(addr, treeIndex, subIndex, isWrite) - - var gas uint64 - if stemRead { - gas += params.WitnessBranchReadCost - } - if selectorRead { - gas += params.WitnessChunkReadCost - } - if stemWrite { - gas += params.WitnessBranchWriteCost - } - if selectorWrite { - gas += params.WitnessChunkWriteCost + _, expected := ae.touchAddressAndChargeGas(addr, *treeIndex, subIndex, isWrite, availableGas) + if expected == 0 && chargeWarmCosts { + expected = params.WarmStorageReadCostEIP2929 } - if selectorFill { - gas += params.WitnessChunkFillCost - } - return gas + return expected } -// touchAddress adds any missing access event to the access event list. -func (ae *AccessEvents) touchAddress(addr common.Address, treeIndex uint256.Int, subIndex byte, isWrite bool) (bool, bool, bool, bool, bool) { +// touchAddressAndChargeGas adds any missing access event to the access event list, and returns the +// consumed and required gas. +func (ae *AccessEvents) touchAddressAndChargeGas(addr common.Address, treeIndex uint256.Int, subIndex byte, isWrite bool, availableGas uint64) (uint64, uint64) { branchKey := newBranchAccessKey(addr, treeIndex) chunkKey := newChunkAccessKey(branchKey, subIndex) @@ -190,11 +188,9 @@ func (ae *AccessEvents) touchAddress(addr common.Address, treeIndex uint256.Int, var branchRead, chunkRead bool if _, hasStem := ae.branches[branchKey]; !hasStem { branchRead = true - ae.branches[branchKey] = AccessWitnessReadFlag } if _, hasSelector := ae.chunks[chunkKey]; !hasSelector { chunkRead = true - ae.chunks[chunkKey] = AccessWitnessReadFlag } // Write access. @@ -202,17 +198,51 @@ func (ae *AccessEvents) touchAddress(addr common.Address, treeIndex uint256.Int, if isWrite { if (ae.branches[branchKey] & AccessWitnessWriteFlag) == 0 { branchWrite = true - ae.branches[branchKey] |= AccessWitnessWriteFlag } chunkValue := ae.chunks[chunkKey] if (chunkValue & AccessWitnessWriteFlag) == 0 { chunkWrite = true - ae.chunks[chunkKey] |= AccessWitnessWriteFlag } - // TODO: charge chunk filling costs if the leaf was previously empty in the state } - return branchRead, chunkRead, branchWrite, chunkWrite, chunkFill + + var gas uint64 + if branchRead { + gas += params.WitnessBranchReadCost + } + if chunkRead { + gas += params.WitnessChunkReadCost + } + if branchWrite { + gas += params.WitnessBranchWriteCost + } + if chunkWrite { + gas += params.WitnessChunkWriteCost + } + if chunkFill { + gas += params.WitnessChunkFillCost + } + + if availableGas < gas { + // consumed != expected + return availableGas, gas + } + + if branchRead { + ae.branches[branchKey] = AccessWitnessReadFlag + } + if branchWrite { + ae.branches[branchKey] |= AccessWitnessWriteFlag + } + if chunkRead { + ae.chunks[chunkKey] = AccessWitnessReadFlag + } + if chunkWrite { + ae.chunks[chunkKey] |= AccessWitnessWriteFlag + } + + // consumed == expected + return gas, gas } type branchAccessKey struct { @@ -240,7 +270,7 @@ func newChunkAccessKey(branchKey branchAccessKey, leafKey byte) chunkAccessKey { } // CodeChunksRangeGas is a helper function to touch every chunk in a code range and charge witness gas costs -func (ae *AccessEvents) CodeChunksRangeGas(contractAddr common.Address, startPC, size uint64, codeLen uint64, isWrite bool) uint64 { +func (ae *AccessEvents) CodeChunksRangeGas(contractAddr common.Address, startPC, size uint64, codeLen uint64, isWrite bool, availableGas uint64) (uint64, uint64) { // note that in the case where the copied code is outside the range of the // contract code but touches the last leaf with contract code in it, // we don't include the last leaf of code in the AccessWitness. The @@ -248,7 +278,7 @@ func (ae *AccessEvents) CodeChunksRangeGas(contractAddr common.Address, startPC, // is already in the AccessWitness so a stateless verifier can see that // the code from the last leaf is not needed. if (codeLen == 0 && size == 0) || startPC > codeLen { - return 0 + return 0, 0 } endPC := startPC + size @@ -263,22 +293,34 @@ func (ae *AccessEvents) CodeChunksRangeGas(contractAddr common.Address, startPC, for chunkNumber := startPC / 31; chunkNumber <= endPC/31; chunkNumber++ { treeIndex := *uint256.NewInt((chunkNumber + 128) / 256) subIndex := byte((chunkNumber + 128) % 256) - gas := ae.touchAddressAndChargeGas(contractAddr, treeIndex, subIndex, isWrite) + consumed, expected := ae.touchAddressAndChargeGas(contractAddr, treeIndex, subIndex, isWrite, availableGas) + // did we OOG ? + if expected > consumed { + return statelessGasCharged + consumed, statelessGasCharged + expected + } var overflow bool - statelessGasCharged, overflow = math.SafeAdd(statelessGasCharged, gas) + statelessGasCharged, overflow = math.SafeAdd(statelessGasCharged, consumed) if overflow { panic("overflow when adding gas") } + availableGas -= consumed } - return statelessGasCharged + return statelessGasCharged, statelessGasCharged } // BasicDataGas adds the account's basic data to the accessed data, and returns the // amount of gas that it costs. // Note that an access in write mode implies an access in read mode, whereas an // access in read mode does not imply an access in write mode. -func (ae *AccessEvents) BasicDataGas(addr common.Address, isWrite bool) uint64 { - return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, isWrite) +func (ae *AccessEvents) BasicDataGas(addr common.Address, isWrite bool, availableGas uint64, chargeWarmCosts bool) uint64 { + _, expected := ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, isWrite, availableGas) + if expected == 0 && chargeWarmCosts { + if availableGas < params.WarmStorageReadCostEIP2929 { + return availableGas + } + expected = params.WarmStorageReadCostEIP2929 + } + return expected } // CodeHashGas adds the account's code hash to the accessed data, and returns the @@ -286,6 +328,13 @@ func (ae *AccessEvents) BasicDataGas(addr common.Address, isWrite bool) uint64 { // in write mode. If false, the charged gas corresponds to an access in read mode. // Note that an access in write mode implies an access in read mode, whereas an access in // read mode does not imply an access in write mode. -func (ae *AccessEvents) CodeHashGas(addr common.Address, isWrite bool) uint64 { - return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, isWrite) +func (ae *AccessEvents) CodeHashGas(addr common.Address, isWrite bool, availableGas uint64, chargeWarmCosts bool) uint64 { + _, expected := ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, isWrite, availableGas) + if expected == 0 && chargeWarmCosts { + if availableGas < params.WarmStorageReadCostEIP2929 { + return availableGas + } + expected = params.WarmStorageReadCostEIP2929 + } + return expected } diff --git a/core/state/access_events_test.go b/core/state/access_events_test.go index 10630b3181..5e1fee767c 100644 --- a/core/state/access_events_test.go +++ b/core/state/access_events_test.go @@ -17,6 +17,7 @@ package state import ( + "math" "testing" "github.com/ethereum/go-ethereum/common" @@ -40,50 +41,50 @@ func TestAccountHeaderGas(t *testing.T) { ae := NewAccessEvents(utils.NewPointCache(1024)) // Check cold read cost - gas := ae.BasicDataGas(testAddr, false) + gas := ae.BasicDataGas(testAddr, false, math.MaxUint64, false) if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost; gas != want { t.Fatalf("incorrect gas computed, got %d, want %d", gas, want) } // Check warm read cost - gas = ae.BasicDataGas(testAddr, false) + gas = ae.BasicDataGas(testAddr, false, math.MaxUint64, false) if gas != 0 { t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0) } // Check cold read costs in the same group no longer incur the branch read cost - gas = ae.CodeHashGas(testAddr, false) + gas = ae.CodeHashGas(testAddr, false, math.MaxUint64, false) if gas != params.WitnessChunkReadCost { t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost) } // Check cold write cost - gas = ae.BasicDataGas(testAddr, true) + gas = ae.BasicDataGas(testAddr, true, math.MaxUint64, false) if want := params.WitnessBranchWriteCost + params.WitnessChunkWriteCost; gas != want { t.Fatalf("incorrect gas computed, got %d, want %d", gas, want) } // Check warm write cost - gas = ae.BasicDataGas(testAddr, true) + gas = ae.BasicDataGas(testAddr, true, math.MaxUint64, false) if gas != 0 { t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0) } // Check a write without a read charges both read and write costs - gas = ae.BasicDataGas(testAddr2, true) + gas = ae.BasicDataGas(testAddr2, true, math.MaxUint64, false) if want := params.WitnessBranchReadCost + params.WitnessBranchWriteCost + params.WitnessChunkWriteCost + params.WitnessChunkReadCost; gas != want { t.Fatalf("incorrect gas computed, got %d, want %d", gas, want) } // Check that a write followed by a read charges nothing - gas = ae.BasicDataGas(testAddr2, false) + gas = ae.BasicDataGas(testAddr2, false, math.MaxUint64, false) if gas != 0 { t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0) } // Check that reading a slot from the account header only charges the // chunk read cost. - gas = ae.SlotGas(testAddr, common.Hash{}, false) + gas = ae.SlotGas(testAddr, common.Hash{}, false, math.MaxUint64, false) if gas != params.WitnessChunkReadCost { t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost) } @@ -100,13 +101,13 @@ func TestContractCreateInitGas(t *testing.T) { } // Check cold read cost, without a value - gas := ae.ContractCreateInitGas(testAddr) + gas, _ := ae.ContractCreateInitGas(testAddr, math.MaxUint64) if want := params.WitnessBranchWriteCost + params.WitnessBranchReadCost + 2*params.WitnessChunkWriteCost + 2*params.WitnessChunkReadCost; gas != want { t.Fatalf("incorrect gas computed, got %d, want %d", gas, want) } // Check warm read cost - gas = ae.ContractCreateInitGas(testAddr) + gas, _ = ae.ContractCreateInitGas(testAddr, math.MaxUint64) if gas != 0 { t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0) } @@ -118,24 +119,24 @@ func TestMessageCallGas(t *testing.T) { ae := NewAccessEvents(utils.NewPointCache(1024)) // Check cold read cost, without a value - gas := ae.MessageCallGas(testAddr) + gas := ae.MessageCallGas(testAddr, math.MaxUint64) if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost; gas != want { t.Fatalf("incorrect gas computed, got %d, want %d", gas, want) } // Check that reading the basic data and code hash of the same account does not incur the branch read cost - gas = ae.BasicDataGas(testAddr, false) + gas = ae.BasicDataGas(testAddr, false, math.MaxUint64, false) if gas != 0 { t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0) } - gas = ae.CodeHashGas(testAddr, false) + gas = ae.CodeHashGas(testAddr, false, math.MaxUint64, false) if gas != params.WitnessChunkReadCost { t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0) } // Check warm read cost - gas = ae.MessageCallGas(testAddr) - if gas != 0 { - t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0) + gas = ae.MessageCallGas(testAddr, math.MaxUint64) + if gas != params.WarmStorageReadCostEIP2929 { + t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WarmStorageReadCostEIP2929) } } diff --git a/core/state_transition.go b/core/state_transition.go index ff2051ddd2..4f172682d0 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -457,7 +457,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { st.evm.AccessEvents.AddTxOrigin(msg.From) if targetAddr := msg.To; targetAddr != nil { - st.evm.AccessEvents.AddTxDestination(*targetAddr, msg.Value.Sign() != 0) + st.evm.AccessEvents.AddTxDestination(*targetAddr, msg.Value.Sign() != 0, !st.state.Exist(*targetAddr)) } } @@ -552,7 +552,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { // add the coinbase to the witness iff the fee is greater than 0 if rules.IsEIP4762 && fee.Sign() != 0 { - st.evm.AccessEvents.AddAccount(st.evm.Context.Coinbase, true) + st.evm.AccessEvents.AddAccount(st.evm.Context.Coinbase, true, math.MaxUint64) } } diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 06849e65ad..784b410802 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -139,7 +139,7 @@ var PrecompiledContractsPrague = PrecompiledContracts{ var PrecompiledContractsBLS = PrecompiledContractsPrague -var PrecompiledContractsVerkle = PrecompiledContractsPrague +var PrecompiledContractsVerkle = PrecompiledContractsBerlin var ( PrecompiledAddressesPrague []common.Address diff --git a/core/vm/eips.go b/core/vm/eips.go index 6159eade7e..d95fa51284 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -339,12 +339,10 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC addr := common.Address(a.Bytes20()) code := interpreter.evm.StateDB.GetCode(addr) paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64()) - if !scope.Contract.IsSystemCall { - statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(code)), false) - if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) { - scope.Contract.Gas = 0 - return nil, ErrOutOfGas - } + consumed, wanted := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(code)), false, scope.Contract.Gas) + scope.Contract.UseGas(consumed, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) + if consumed < wanted { + return nil, ErrOutOfGas } scope.Memory.Set(memOffset.Uint64(), length.Uint64(), paddedCodeCopy) @@ -367,9 +365,9 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext // touch next chunk if PUSH1 is at the boundary. if so, *pc has // advanced past this boundary. contractAddr := scope.Contract.Address() - statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, *pc+1, uint64(1), uint64(len(scope.Contract.Code)), false) - if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) { - scope.Contract.Gas = 0 + consumed, wanted := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, *pc+1, uint64(1), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas) + scope.Contract.UseGas(wanted, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) + if consumed < wanted { return nil, ErrOutOfGas } } @@ -395,9 +393,9 @@ func makePushEIP4762(size uint64, pushByteSize int) executionFunc { if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall { contractAddr := scope.Contract.Address() - statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false) - if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) { - scope.Contract.Gas = 0 + consumed, wanted := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas) + scope.Contract.UseGas(consumed, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) + if consumed < wanted { return nil, ErrOutOfGas } } diff --git a/core/vm/evm.go b/core/vm/evm.go index ecb0f118ec..b45a434545 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -206,8 +206,14 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP4762 && !isSystemCall(caller) { - // add proof of absence to witness - wgas := evm.AccessEvents.AddAccount(addr, false) + // Add proof of absence to witness + // At this point, the read costs have already been charged, either because this + // is a direct tx call, in which case it's covered by the intrinsic gas, or because + // of a CALL instruction, in which case BASIC_DATA has been added to the access + // list in write mode. If there is enough gas paying for the addition of the code + // hash leaf to the access list, then account creation will proceed unimpaired. + // Thus, only pay for the creation of the code hash leaf here. + wgas := evm.AccessEvents.CodeHashGas(addr, true, gas, false) if gas < wgas { evm.StateDB.RevertToSnapshot(snapshot) return nil, 0, ErrOutOfGas @@ -433,7 +439,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui // Charge the contract creation init gas in verkle mode if evm.chainRules.IsEIP4762 { - statelessGas := evm.AccessEvents.ContractCreatePreCheckGas(address) + statelessGas := evm.AccessEvents.ContractCreatePreCheckGas(address, gas) if statelessGas > gas { return nil, common.Address{}, 0, ErrOutOfGas } @@ -481,14 +487,14 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui } // Charge the contract creation init gas in verkle mode if evm.chainRules.IsEIP4762 { - statelessGas := evm.AccessEvents.ContractCreateInitGas(address) - if statelessGas > gas { + consumed, wanted := evm.AccessEvents.ContractCreateInitGas(address, gas) + if consumed < wanted { return nil, common.Address{}, 0, ErrOutOfGas } if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { - evm.Config.Tracer.OnGasChange(gas, gas-statelessGas, tracing.GasChangeWitnessContractInit) + evm.Config.Tracer.OnGasChange(gas, gas-consumed, tracing.GasChangeWitnessContractInit) } - gas = gas - statelessGas + gas = gas - consumed } evm.Context.Transfer(evm.StateDB, caller, address, value) @@ -535,7 +541,9 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]b return ret, ErrCodeStoreOutOfGas } } else { - if len(ret) > 0 && !contract.UseGas(evm.AccessEvents.CodeChunksRangeGas(address, 0, uint64(len(ret)), uint64(len(ret)), true), evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk) { + consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(address, 0, uint64(len(ret)), uint64(len(ret)), true, contract.Gas) + contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk) + if len(ret) > 0 && (consumed < wanted) { return ret, ErrCodeStoreOutOfGas } } diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 55855727b5..f711aa4a18 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -394,14 +394,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { return 0, ErrGasUintOverflow } - if evm.chainRules.IsEIP4762 && !contract.IsSystemCall { - if transfersValue { - gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address)) - if overflow { - return 0, ErrGasUintOverflow - } - } - } + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err @@ -428,16 +421,6 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { return 0, ErrGasUintOverflow } - if evm.chainRules.IsEIP4762 && !contract.IsSystemCall { - address := common.Address(stack.Back(1).Bytes20()) - transfersValue := !stack.Back(2).IsZero() - if transfersValue { - gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address)) - if overflow { - return 0, ErrGasUintOverflow - } - } - } evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index a62c3c843d..d0e5967e6e 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -237,7 +237,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // if the PC ends up in a new "chunk" of verkleized code, charge the // associated costs. contractAddr := contract.Address() - contract.Gas -= in.evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, pc, 1, uint64(len(contract.Code)), false) + consumed, wanted := in.evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, pc, 1, uint64(len(contract.Code)), false, contract.Gas) + contract.UseGas(consumed, in.evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk) + if consumed < wanted { + return nil, ErrOutOfGas + } } // Get the operation from the jump table and validate the stack to ensure there are diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index ee811b447e..26b9473fe8 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -87,7 +87,7 @@ func validate(jt JumpTable) JumpTable { } func newVerkleInstructionSet() JumpTable { - instructionSet := newCancunInstructionSet() + instructionSet := newShanghaiInstructionSet() enable4762(&instructionSet) return validate(instructionSet) } diff --git a/core/vm/operations_verkle.go b/core/vm/operations_verkle.go index 751761a911..30f9957775 100644 --- a/core/vm/operations_verkle.go +++ b/core/vm/operations_verkle.go @@ -25,31 +25,16 @@ import ( ) func gasSStore4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas := evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), true) - if gas == 0 { - gas = params.WarmStorageReadCostEIP2929 - } - return gas, nil + return evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), true, contract.Gas, true), nil } func gasSLoad4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas := evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), false) - if gas == 0 { - gas = params.WarmStorageReadCostEIP2929 - } - return gas, nil + return evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), false, contract.Gas, true), nil } func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - if contract.IsSystemCall { - return 0, nil - } address := stack.peek().Bytes20() - gas := evm.AccessEvents.BasicDataGas(address, false) - if gas == 0 { - gas = params.WarmStorageReadCostEIP2929 - } - return gas, nil + return evm.AccessEvents.BasicDataGas(address, false, contract.Gas, true), nil } func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { @@ -57,56 +42,69 @@ func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, if _, isPrecompile := evm.precompile(address); isPrecompile { return 0, nil } - if contract.IsSystemCall { - return 0, nil - } - gas := evm.AccessEvents.BasicDataGas(address, false) - if gas == 0 { - gas = params.WarmStorageReadCostEIP2929 - } - return gas, nil + return evm.AccessEvents.BasicDataGas(address, false, contract.Gas, true), nil } func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - if contract.IsSystemCall { - return 0, nil - } address := stack.peek().Bytes20() if _, isPrecompile := evm.precompile(address); isPrecompile { return 0, nil } - gas := evm.AccessEvents.CodeHashGas(address, false) - if gas == 0 { - gas = params.WarmStorageReadCostEIP2929 - } - return gas, nil + return evm.AccessEvents.CodeHashGas(address, false, contract.Gas, true), nil } -func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc { +func makeCallVariantGasEIP4762(oldCalculator gasFunc, withTransferCosts bool) gasFunc { return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := oldCalculator(evm, contract, stack, mem, memorySize) - if err != nil { - return 0, err - } - if contract.IsSystemCall { - return gas, nil - } - if _, isPrecompile := evm.precompile(contract.Address()); isPrecompile { - return gas, nil - } - witnessGas := evm.AccessEvents.MessageCallGas(contract.Address()) - if witnessGas == 0 { + var ( + target = common.Address(stack.Back(1).Bytes20()) + witnessGas uint64 + _, isPrecompile = evm.precompile(target) + isSystemContract = target == params.HistoryStorageAddress + ) + + // If value is transferred, it is charged before 1/64th + // is subtracted from the available gas pool. + if withTransferCosts && !stack.Back(2).IsZero() { + wantedValueTransferWitnessGas := evm.AccessEvents.ValueTransferGas(contract.Address(), target, contract.Gas) + if wantedValueTransferWitnessGas > contract.Gas { + return wantedValueTransferWitnessGas, nil + } + witnessGas = wantedValueTransferWitnessGas + } else if isPrecompile || isSystemContract { witnessGas = params.WarmStorageReadCostEIP2929 + } else { + // The charging for the value transfer is done BEFORE subtracting + // the 1/64th gas, as this is considered part of the CALL instruction. + // (so before we get to this point) + // But the message call is part of the subcall, for which only 63/64th + // of the gas should be available. + wantedMessageCallWitnessGas := evm.AccessEvents.MessageCallGas(target, contract.Gas-witnessGas) + var overflow bool + if witnessGas, overflow = math.SafeAdd(witnessGas, wantedMessageCallWitnessGas); overflow { + return 0, ErrGasUintOverflow + } + if witnessGas > contract.Gas { + return witnessGas, nil + } + } + + contract.Gas -= witnessGas + // if the operation fails, adds witness gas to the gas before returning the error + gas, err := oldCalculator(evm, contract, stack, mem, memorySize) + contract.Gas += witnessGas // restore witness gas so that it can be charged at the callsite + var overflow bool + if gas, overflow = math.SafeAdd(gas, witnessGas); overflow { + return 0, ErrGasUintOverflow } - return witnessGas + gas, nil + return gas, err } } var ( - gasCallEIP4762 = makeCallVariantGasEIP4762(gasCall) - gasCallCodeEIP4762 = makeCallVariantGasEIP4762(gasCallCode) - gasStaticCallEIP4762 = makeCallVariantGasEIP4762(gasStaticCall) - gasDelegateCallEIP4762 = makeCallVariantGasEIP4762(gasDelegateCall) + gasCallEIP4762 = makeCallVariantGasEIP4762(gasCall, true) + gasCallCodeEIP4762 = makeCallVariantGasEIP4762(gasCallCode, false) + gasStaticCallEIP4762 = makeCallVariantGasEIP4762(gasStaticCall, false) + gasDelegateCallEIP4762 = makeCallVariantGasEIP4762(gasDelegateCall, false) ) func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { @@ -118,15 +116,44 @@ func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Mem return 0, nil } contractAddr := contract.Address() - statelessGas := evm.AccessEvents.BasicDataGas(contractAddr, false) + wanted := evm.AccessEvents.BasicDataGas(contractAddr, false, contract.Gas, false) + if wanted > contract.Gas { + return wanted, nil + } + statelessGas := wanted + balanceIsZero := evm.StateDB.GetBalance(contractAddr).Sign() == 0 + _, isPrecompile := evm.precompile(beneficiaryAddr) + isSystemContract := beneficiaryAddr == params.HistoryStorageAddress + + if (isPrecompile || isSystemContract) && balanceIsZero { + return statelessGas, nil + } + if contractAddr != beneficiaryAddr { - statelessGas += evm.AccessEvents.BasicDataGas(beneficiaryAddr, false) + wanted := evm.AccessEvents.BasicDataGas(beneficiaryAddr, false, contract.Gas-statelessGas, false) + if wanted > contract.Gas-statelessGas { + return statelessGas + wanted, nil + } + statelessGas += wanted } // Charge write costs if it transfers value - if evm.StateDB.GetBalance(contractAddr).Sign() != 0 { - statelessGas += evm.AccessEvents.BasicDataGas(contractAddr, true) + if !balanceIsZero { + wanted := evm.AccessEvents.BasicDataGas(contractAddr, true, contract.Gas-statelessGas, false) + if wanted > contract.Gas-statelessGas { + return statelessGas + wanted, nil + } + statelessGas += wanted + if contractAddr != beneficiaryAddr { - statelessGas += evm.AccessEvents.BasicDataGas(beneficiaryAddr, true) + if evm.StateDB.Exist(beneficiaryAddr) { + wanted = evm.AccessEvents.BasicDataGas(beneficiaryAddr, true, contract.Gas-statelessGas, false) + } else { + wanted = evm.AccessEvents.AddAccount(beneficiaryAddr, true, contract.Gas-statelessGas) + } + if wanted > contract.Gas-statelessGas { + return statelessGas + wanted, nil + } + statelessGas += wanted } } return statelessGas, nil @@ -137,17 +164,19 @@ func gasCodeCopyEip4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, if err != nil { return 0, err } - var ( - codeOffset = stack.Back(1) - length = stack.Back(2) - ) - uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() - if overflow { - uint64CodeOffset = gomath.MaxUint64 - } - _, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(contract.Code, uint64CodeOffset, length.Uint64()) if !contract.IsDeployment && !contract.IsSystemCall { - gas += evm.AccessEvents.CodeChunksRangeGas(contract.Address(), copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false) + var ( + codeOffset = stack.Back(1) + length = stack.Back(2) + ) + uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() + if overflow { + uint64CodeOffset = gomath.MaxUint64 + } + + _, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(contract.Code, uint64CodeOffset, length.Uint64()) + _, wanted := evm.AccessEvents.CodeChunksRangeGas(contract.Address(), copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false, contract.Gas-gas) + gas += wanted } return gas, nil } @@ -158,16 +187,17 @@ func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memo if err != nil { return 0, err } - if contract.IsSystemCall { - return gas, nil - } addr := common.Address(stack.peek().Bytes20()) - wgas := evm.AccessEvents.BasicDataGas(addr, false) - if wgas == 0 { - wgas = params.WarmStorageReadCostEIP2929 + _, isPrecompile := evm.precompile(addr) + if isPrecompile || addr == params.HistoryStorageAddress { + var overflow bool + if gas, overflow = math.SafeAdd(gas, params.WarmStorageReadCostEIP2929); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil } + wgas := evm.AccessEvents.BasicDataGas(addr, false, contract.Gas-gas, true) var overflow bool - // We charge (cold-warm), since 'warm' is already charged as constantGas if gas, overflow = math.SafeAdd(gas, wgas); overflow { return 0, ErrGasUintOverflow } From 85b26f3d6841fb1bc90a77ada7e9cf62988c8cc0 Mon Sep 17 00:00:00 2001 From: Charlotte <69423184+tqpcharlie@users.noreply.github.com> Date: Thu, 15 May 2025 15:55:38 -0400 Subject: [PATCH 025/365] AUTHORS, .mailmap: update name and email attribution (#31624) --- .mailmap | 7 ++++--- AUTHORS | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.mailmap b/.mailmap index 92a9e07748..597da62dc3 100644 --- a/.mailmap +++ b/.mailmap @@ -50,6 +50,10 @@ Boqin Qin Casey Detrio +Charlotte +Charlotte +Charlotte + Cheng Li Chris Ziogas @@ -301,9 +305,6 @@ Yohann Léon yzb <335357057@qq.com> yzb <335357057@qq.com> -Zachinquarantine -Zachinquarantine - Ziyuan Zhong Zsolt Felföldi diff --git a/AUTHORS b/AUTHORS index 1ec240aeb6..da482717c6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -123,6 +123,7 @@ Ceyhun Onur chabashilah changhong Charles Cooper +Charlotte Chase Wright Chawin Aiemvaravutigul Chen Quan @@ -839,7 +840,6 @@ ywzqwwt <39263032+ywzqwwt@users.noreply.github.com> yzb <335357057@qq.com> zaccoding Zach -Zachinquarantine zah Zahoor Mohamed Zak Cole From 3ceec0ea9bd66346071512587cb2bdbd7160e48f Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 15 May 2025 22:53:26 +0200 Subject: [PATCH 026/365] cmd/geth, internal/era/eradl: add era1 downloader tool (#31823) This adds a geth subcommand for downloading era1 files and placing them into the correct location. The tool can be used even while geth is already running on the datadir. Downloads are checked against a hard-coded list of checksums for mainnet and sepolia. ``` ./geth download-era --server $SERVER --block 333333 ./geth download-era --server $SERVER --block 333333-444444 ./geth download-era --server $SERVER --epoch 0-10 ./geth download-era --server $SERVER --all ``` The implementation reuses the file downloader we already had for fetching build tools. I've done some refactoring on it to make sure it can support the new use case, and there are some changes to the build here as well. --- build/ci.go | 55 +- cmd/geth/chaincmd.go | 122 +- cmd/geth/main.go | 3 +- internal/build/download.go | 151 -- internal/build/gotool.go | 54 +- internal/download/download.go | 298 ++++ internal/era/eradl/checksums_mainnet.txt | 1897 ++++++++++++++++++++++ internal/era/eradl/checksums_sepolia.txt | 183 +++ internal/era/eradl/eradl.go | 115 ++ 9 files changed, 2642 insertions(+), 236 deletions(-) delete mode 100644 internal/build/download.go create mode 100644 internal/download/download.go create mode 100644 internal/era/eradl/checksums_mainnet.txt create mode 100644 internal/era/eradl/checksums_sepolia.txt create mode 100644 internal/era/eradl/eradl.go diff --git a/build/ci.go b/build/ci.go index b2ff829d3f..88e4e82282 100644 --- a/build/ci.go +++ b/build/ci.go @@ -59,6 +59,7 @@ import ( "github.com/cespare/cp" "github.com/ethereum/go-ethereum/crypto/signify" "github.com/ethereum/go-ethereum/internal/build" + "github.com/ethereum/go-ethereum/internal/download" "github.com/ethereum/go-ethereum/internal/version" ) @@ -190,7 +191,7 @@ func doInstall(cmdline []string) { // Configure the toolchain. tc := build.GoToolchain{GOARCH: *arch, CC: *cc} if *dlgo { - csdb := build.MustLoadChecksums("build/checksums.txt") + csdb := download.MustLoadChecksums("build/checksums.txt") tc.Root = build.DownloadGo(csdb) } // Disable CLI markdown doc generation in release builds. @@ -285,7 +286,7 @@ func doTest(cmdline []string) { flag.CommandLine.Parse(cmdline) // Get test fixtures. - csdb := build.MustLoadChecksums("build/checksums.txt") + csdb := download.MustLoadChecksums("build/checksums.txt") downloadSpecTestFixtures(csdb, *cachedir) // Configure the toolchain. @@ -329,16 +330,11 @@ func doTest(cmdline []string) { } // 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) - } +func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string { ext := ".tar.gz" base := "fixtures_pectra-devnet-6" // TODO(s1na) rename once the version becomes part of the filename - url := fmt.Sprintf("https://github.com/ethereum/execution-spec-tests/releases/download/%s/%s%s", executionSpecTestsVersion, base, ext) archivePath := filepath.Join(cachedir, base+ext) - if err := csdb.DownloadFile(url, archivePath); err != nil { + if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil { log.Fatal(err) } if err := build.ExtractArchive(archivePath, executionSpecTestsDir); err != nil { @@ -444,14 +440,13 @@ func doLint(cmdline []string) { // downloadLinter downloads and unpacks golangci-lint. func downloadLinter(cachedir string) string { - csdb := build.MustLoadChecksums("build/checksums.txt") - version, err := build.Version(csdb, "golangci") + csdb := download.MustLoadChecksums("build/checksums.txt") + version, err := csdb.FindVersion("golangci") if err != nil { log.Fatal(err) } arch := runtime.GOARCH ext := ".tar.gz" - if runtime.GOOS == "windows" { ext = ".zip" } @@ -459,9 +454,8 @@ func downloadLinter(cachedir string) string { arch += "v" + os.Getenv("GOARM") } base := fmt.Sprintf("golangci-lint-%s-%s-%s", version, runtime.GOOS, arch) - url := fmt.Sprintf("https://github.com/golangci/golangci-lint/releases/download/v%s/%s%s", version, base, ext) archivePath := filepath.Join(cachedir, base+ext) - if err := csdb.DownloadFile(url, archivePath); err != nil { + if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil { log.Fatal(err) } if err := build.ExtractArchive(archivePath, cachedir); err != nil { @@ -497,8 +491,8 @@ func protocArchiveBaseName() (string, error) { // in the generate command. It returns the full path of the directory // containing the 'protoc-gen-go' executable. func downloadProtocGenGo(cachedir string) string { - csdb := build.MustLoadChecksums("build/checksums.txt") - version, err := build.Version(csdb, "protoc-gen-go") + csdb := download.MustLoadChecksums("build/checksums.txt") + version, err := csdb.FindVersion("protoc-gen-go") if err != nil { log.Fatal(err) } @@ -510,10 +504,8 @@ func downloadProtocGenGo(cachedir string) string { archiveName += ".tar.gz" } - url := fmt.Sprintf("https://github.com/protocolbuffers/protobuf-go/releases/download/v%s/%s", version, archiveName) - archivePath := path.Join(cachedir, archiveName) - if err := csdb.DownloadFile(url, archivePath); err != nil { + if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil { log.Fatal(err) } extractDest := filepath.Join(cachedir, baseName) @@ -531,8 +523,8 @@ func downloadProtocGenGo(cachedir string) string { // files as a CI step. It returns the full path to the directory containing // the protoc executable. func downloadProtoc(cachedir string) string { - csdb := build.MustLoadChecksums("build/checksums.txt") - version, err := build.Version(csdb, "protoc") + csdb := download.MustLoadChecksums("build/checksums.txt") + version, err := csdb.FindVersion("protoc") if err != nil { log.Fatal(err) } @@ -543,10 +535,8 @@ func downloadProtoc(cachedir string) string { fileName := fmt.Sprintf("protoc-%s-%s", version, baseName) archiveFileName := fileName + ".zip" - url := fmt.Sprintf("https://github.com/protocolbuffers/protobuf/releases/download/v%s/%s", version, archiveFileName) archivePath := filepath.Join(cachedir, archiveFileName) - - if err := csdb.DownloadFile(url, archivePath); err != nil { + if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil { log.Fatal(err) } extractDest := filepath.Join(cachedir, fileName) @@ -826,18 +816,17 @@ func doDebianSource(cmdline []string) { // downloadGoBootstrapSources downloads the Go source tarball(s) that will be used // to bootstrap the builder Go. func downloadGoBootstrapSources(cachedir string) []string { - csdb := build.MustLoadChecksums("build/checksums.txt") + csdb := download.MustLoadChecksums("build/checksums.txt") var bundles []string for _, booter := range []string{"ppa-builder-1.19", "ppa-builder-1.21", "ppa-builder-1.23"} { - gobootVersion, err := build.Version(csdb, booter) + gobootVersion, err := csdb.FindVersion(booter) 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 { + if err := csdb.DownloadFileFromKnownURL(dst); err != nil { log.Fatal(err) } bundles = append(bundles, dst) @@ -847,15 +836,14 @@ func downloadGoBootstrapSources(cachedir string) []string { // downloadGoSources downloads the Go source tarball. func downloadGoSources(cachedir string) string { - csdb := build.MustLoadChecksums("build/checksums.txt") - dlgoVersion, err := build.Version(csdb, "golang") + csdb := download.MustLoadChecksums("build/checksums.txt") + dlgoVersion, err := csdb.FindVersion("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) - if err := csdb.DownloadFile(url, dst); err != nil { + if err := csdb.DownloadFileFromKnownURL(dst); err != nil { log.Fatal(err) } return dst @@ -1181,5 +1169,6 @@ func doPurge(cmdline []string) { } func doSanityCheck() { - build.DownloadAndVerifyChecksums(build.MustLoadChecksums("build/checksums.txt")) + csdb := download.MustLoadChecksums("build/checksums.txt") + csdb.DownloadAndVerifyAll() } diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index a947f35f2f..dc071725c1 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -21,9 +21,12 @@ import ( "errors" "fmt" "os" + "path/filepath" + "regexp" "runtime" "slices" "strconv" + "strings" "sync/atomic" "time" @@ -39,6 +42,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/era" + "github.com/ethereum/go-ethereum/internal/era/eradl" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -190,7 +194,7 @@ This command dumps out the state for a given block (or latest, if none provided) `, } - pruneCommand = &cli.Command{ + pruneHistoryCommand = &cli.Command{ Action: pruneHistory, Name: "prune-history", Usage: "Prune blockchain history (block bodies and receipts) up to the merge block", @@ -201,6 +205,42 @@ The prune-history command removes historical block bodies and receipts from the blockchain database up to the merge block, while preserving block headers. This helps reduce storage requirements for nodes that don't need full historical data.`, } + + downloadEraCommand = &cli.Command{ + Action: downloadEra, + Name: "download-era", + Usage: "Fetches era1 files (pre-merge history) from an HTTP endpoint", + ArgsUsage: "", + Flags: slices.Concat( + utils.DatabaseFlags, + utils.NetworkFlags, + []cli.Flag{ + eraBlockFlag, + eraEpochFlag, + eraAllFlag, + eraServerFlag, + }, + ), + } +) + +var ( + eraBlockFlag = &cli.StringFlag{ + Name: "block", + Usage: "Block number to fetch. (can also be a range -)", + } + eraEpochFlag = &cli.StringFlag{ + Name: "epoch", + Usage: "Epoch number to fetch (can also be a range -)", + } + eraAllFlag = &cli.BoolFlag{ + Name: "all", + Usage: "Download all available era1 files", + } + eraServerFlag = &cli.StringFlag{ + Name: "server", + Usage: "era1 server URL", + } ) // initGenesis will initialise the given JSON format genesis file and writes it as @@ -665,3 +705,83 @@ func pruneHistory(ctx *cli.Context) error { return nil } + +// downladEra is the era1 file downloader tool. +func downloadEra(ctx *cli.Context) error { + flags.CheckExclusive(ctx, eraBlockFlag, eraEpochFlag, eraAllFlag) + + // Resolve the network. + var network = "mainnet" + if utils.IsNetworkPreset(ctx) { + switch { + case ctx.IsSet(utils.MainnetFlag.Name): + case ctx.IsSet(utils.SepoliaFlag.Name): + network = "sepolia" + default: + return fmt.Errorf("unsupported network, no known era1 checksums") + } + } + + // Resolve the destination directory. + stack, _ := makeConfigNode(ctx) + defer stack.Close() + ancients := stack.ResolveAncient("chaindata", "") + dir := filepath.Join(ancients, "era") + + baseURL := ctx.String(eraServerFlag.Name) + if baseURL == "" { + return fmt.Errorf("need --%s flag to download", eraServerFlag.Name) + } + + l, err := eradl.New(baseURL, network) + if err != nil { + return err + } + switch { + case ctx.IsSet(eraAllFlag.Name): + return l.DownloadAll(dir) + + case ctx.IsSet(eraBlockFlag.Name): + s := ctx.String(eraBlockFlag.Name) + start, end, ok := parseRange(s) + if !ok { + return fmt.Errorf("invalid block range: %q", s) + } + return l.DownloadBlockRange(start, end, dir) + + case ctx.IsSet(eraEpochFlag.Name): + s := ctx.String(eraEpochFlag.Name) + start, end, ok := parseRange(s) + if !ok { + return fmt.Errorf("invalid epoch range: %q", s) + } + return l.DownloadEpochRange(start, end, dir) + + default: + return fmt.Errorf("specify one of --%s, --%s, or --%s to download", eraAllFlag.Name, eraBlockFlag.Name, eraEpochFlag.Name) + } +} + +func parseRange(s string) (start uint64, end uint64, ok bool) { + if m, _ := regexp.MatchString("[0-9]+", s); m { + start, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return 0, 0, false + } + end = start + return start, end, true + } + if m, _ := regexp.MatchString("[0-9]+-[0-9]+", s); m { + s1, s2, _ := strings.Cut(s, "-") + start, err := strconv.ParseUint(s1, 10, 64) + if err != nil { + return 0, 0, false + } + end, err = strconv.ParseUint(s2, 10, 64) + if err != nil { + return 0, 0, false + } + return start, end, true + } + return 0, 0, false +} diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 289030ae65..bdff96e369 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -225,7 +225,8 @@ func init() { removedbCommand, dumpCommand, dumpGenesisCommand, - pruneCommand, + pruneHistoryCommand, + downloadEraCommand, // See accountcmd.go: accountCommand, walletCommand, diff --git a/internal/build/download.go b/internal/build/download.go deleted file mode 100644 index 50268227a5..0000000000 --- a/internal/build/download.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2019 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 . - -package build - -import ( - "bufio" - "crypto/sha256" - "encoding/hex" - "fmt" - "io" - "log" - "net/http" - "os" - "path/filepath" - "strings" -) - -// ChecksumDB keeps file checksums. -type ChecksumDB struct { - allChecksums []string -} - -// MustLoadChecksums loads a file containing checksums. -func MustLoadChecksums(file string) *ChecksumDB { - content, err := os.ReadFile(file) - if err != nil { - log.Fatal("can't load checksum file: " + err.Error()) - } - return &ChecksumDB{strings.Split(strings.ReplaceAll(string(content), "\r\n", "\n"), "\n")} -} - -// Verify checks whether the given file is valid according to the checksum database. -func (db *ChecksumDB) Verify(path string) error { - fd, err := os.Open(path) - if err != nil { - return err - } - defer fd.Close() - - h := sha256.New() - if _, err := io.Copy(h, bufio.NewReader(fd)); err != nil { - return err - } - fileHash := hex.EncodeToString(h.Sum(nil)) - if !db.findHash(filepath.Base(path), fileHash) { - return fmt.Errorf("invalid file hash: %s %s", fileHash, filepath.Base(path)) - } - return nil -} - -func (db *ChecksumDB) findHash(basename, hash string) bool { - want := hash + " " + basename - for _, line := range db.allChecksums { - if strings.TrimSpace(line) == want { - return true - } - } - return false -} - -// DownloadFile downloads a file and verifies its checksum. -func (db *ChecksumDB) DownloadFile(url, dstPath string) error { - if err := db.Verify(dstPath); err == nil { - fmt.Printf("%s is up-to-date\n", dstPath) - return nil - } - fmt.Printf("%s is stale\n", dstPath) - fmt.Printf("downloading from %s\n", url) - - resp, err := http.Get(url) - if err != nil { - return fmt.Errorf("download error: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("download error: status %d", resp.StatusCode) - } - if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil { - return err - } - fd, err := os.OpenFile(dstPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) - if err != nil { - return err - } - dst := newDownloadWriter(fd, resp.ContentLength) - _, err = io.Copy(dst, resp.Body) - dst.Close() - if err != nil { - return err - } - return db.Verify(dstPath) -} - -type downloadWriter struct { - file *os.File - dstBuf *bufio.Writer - size int64 - written int64 - lastpct int64 -} - -func newDownloadWriter(dst *os.File, size int64) *downloadWriter { - return &downloadWriter{ - file: dst, - dstBuf: bufio.NewWriter(dst), - size: size, - } -} - -func (w *downloadWriter) Write(buf []byte) (int, error) { - n, err := w.dstBuf.Write(buf) - - // Report progress. - w.written += int64(n) - pct := w.written * 10 / w.size * 10 - if pct != w.lastpct { - if w.lastpct != 0 { - fmt.Print("...") - } - fmt.Print(pct, "%") - w.lastpct = pct - } - return n, err -} - -func (w *downloadWriter) Close() error { - if w.lastpct > 0 { - fmt.Println() // Finish the progress line. - } - flushErr := w.dstBuf.Flush() - closeErr := w.file.Close() - if flushErr != nil { - return flushErr - } - return closeErr -} diff --git a/internal/build/gotool.go b/internal/build/gotool.go index 2a47460418..172fa13464 100644 --- a/internal/build/gotool.go +++ b/internal/build/gotool.go @@ -24,6 +24,8 @@ import ( "path/filepath" "runtime" "strings" + + "github.com/ethereum/go-ethereum/internal/download" ) type GoToolchain struct { @@ -84,8 +86,8 @@ func (g *GoToolchain) goTool(command string, args ...string) *exec.Cmd { // DownloadGo downloads the Go binary distribution and unpacks it into a temporary // directory. It returns the GOROOT of the unpacked toolchain. -func DownloadGo(csdb *ChecksumDB) string { - version, err := Version(csdb, "golang") +func DownloadGo(csdb *download.ChecksumDB) string { + version, err := csdb.FindVersion("golang") if err != nil { log.Fatal(err) } @@ -130,51 +132,3 @@ func DownloadGo(csdb *ChecksumDB) string { } return goroot } - -// Version returns the versions defined in the checksumdb. -func Version(csdb *ChecksumDB, version string) (string, error) { - for _, l := range csdb.allChecksums { - if !strings.HasPrefix(l, "# version:") { - continue - } - v := strings.Split(l, ":")[1] - parts := strings.Split(v, " ") - if len(parts) != 2 { - log.Print("Erroneous version-string", "v", l) - continue - } - if parts[0] == version { - return parts[1], nil - } - } - return "", fmt.Errorf("no version found for '%v'", version) -} - -// DownloadAndVerifyChecksums downloads all files and checks that they match -// the checksum given in checksums.txt. -// This task can be used to sanity-check new checksums. -func DownloadAndVerifyChecksums(csdb *ChecksumDB) { - var ( - base = "" - ucache = os.TempDir() - ) - for _, l := range csdb.allChecksums { - if strings.HasPrefix(l, "# https://") { - base = l[2:] - continue - } - if strings.HasPrefix(l, "#") { - continue - } - hashFile := strings.Split(l, " ") - if len(hashFile) != 2 { - continue - } - file := hashFile[1] - url := base + file - dst := filepath.Join(ucache, file) - if err := csdb.DownloadFile(url, dst); err != nil { - log.Print(err) - } - } -} diff --git a/internal/download/download.go b/internal/download/download.go new file mode 100644 index 0000000000..26c7795ce5 --- /dev/null +++ b/internal/download/download.go @@ -0,0 +1,298 @@ +// Copyright 2019 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 . + +// Package download implements checksum-verified file downloads. +package download + +import ( + "bufio" + "bytes" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "iter" + "net/http" + "net/url" + "os" + "path/filepath" + "strings" +) + +// ChecksumDB keeps file checksums and tool versions. +type ChecksumDB struct { + hashes []hashEntry + versions []versionEntry +} + +type versionEntry struct { + name string + version string +} + +type hashEntry struct { + hash string + file string + url *url.URL +} + +// MustLoadChecksums loads a file containing checksums. +func MustLoadChecksums(file string) *ChecksumDB { + content, err := os.ReadFile(file) + if err != nil { + panic("can't load checksum file: " + err.Error()) + } + db, err := ParseChecksums(content) + if err != nil { + panic(fmt.Sprintf("invalid checksums in %s: %v", file, err)) + } + return db +} + +// ParseChecksums parses a checksum database. +func ParseChecksums(input []byte) (*ChecksumDB, error) { + var ( + csdb = new(ChecksumDB) + rd = bytes.NewBuffer(input) + lastURL *url.URL + ) + for lineNum := 1; ; lineNum++ { + line, err := rd.ReadString('\n') + if err == io.EOF { + break + } + line = strings.TrimSpace(line) + switch { + case line == "": + // Blank lines are allowed, and they reset the current urlEntry. + lastURL = nil + + case strings.HasPrefix(line, "#"): + // It's a comment. Some comments have special meaning. + content := strings.TrimLeft(line, "# ") + switch { + case strings.HasPrefix(content, "version:"): + // Version comments define the version of a tool. + v := strings.Split(content, ":")[1] + parts := strings.Split(v, " ") + if len(parts) != 2 { + return nil, fmt.Errorf("line %d: invalid version string: %q", lineNum, v) + } + csdb.versions = append(csdb.versions, versionEntry{parts[0], parts[1]}) + + case strings.HasPrefix(content, "https://") || strings.HasPrefix(content, "http://"): + // URL comments define the URL where the following files are found. Here + // we keep track of the last found urlEntry and attach it to each file later. + u, err := url.Parse(content) + if err != nil { + return nil, fmt.Errorf("line %d: invalid URL: %v", lineNum, err) + } + lastURL = u + } + + default: + // It's a file hash entry. + fields := strings.Fields(line) + if len(fields) != 2 { + return nil, fmt.Errorf("line %d: invalid number of space-separated fields (%d)", lineNum, len(fields)) + } + csdb.hashes = append(csdb.hashes, hashEntry{fields[0], fields[1], lastURL}) + } + } + return csdb, nil +} + +// Files returns an iterator over all file names. +func (db *ChecksumDB) Files() iter.Seq[string] { + return func(yield func(string) bool) { + for _, e := range db.hashes { + if !yield(e.file) { + return + } + } + } +} + +// DownloadAndVerifyAll downloads all files and checks that they match the checksum given in +// the database. This task can be used to sanity-check new checksums. +func (db *ChecksumDB) DownloadAndVerifyAll() { + var tmp = os.TempDir() + for _, e := range db.hashes { + if e.url == nil { + fmt.Printf("Skipping verification of %s: no URL defined in checksum database", e.file) + continue + } + url := e.url.JoinPath(e.file).String() + dst := filepath.Join(tmp, e.file) + if err := db.DownloadFile(url, dst); err != nil { + fmt.Println("error:", err) + } + } +} + +// verifyHash checks that the file at 'path' has the expected hash. +func verifyHash(path, expectedHash string) error { + fd, err := os.Open(path) + if err != nil { + return err + } + defer fd.Close() + + h := sha256.New() + if _, err := io.Copy(h, bufio.NewReader(fd)); err != nil { + return err + } + fileHash := hex.EncodeToString(h.Sum(nil)) + if fileHash != expectedHash { + return fmt.Errorf("invalid file hash: %s %s", fileHash, filepath.Base(path)) + } + return nil +} + +// DownloadFileFromKnownURL downloads a file from the URL defined in the checksum database. +func (db *ChecksumDB) DownloadFileFromKnownURL(dstPath string) error { + base := filepath.Base(dstPath) + url, err := db.FindURL(base) + if err != nil { + return err + } + return db.DownloadFile(url, dstPath) +} + +// DownloadFile downloads a file and verifies its checksum. +func (db *ChecksumDB) DownloadFile(url, dstPath string) error { + basename := filepath.Base(dstPath) + hash := db.findHash(basename) + if hash == "" { + return fmt.Errorf("no known hash for file %q", basename) + } + // Shortcut if already downloaded. + if verifyHash(dstPath, hash) == nil { + fmt.Printf("%s is up-to-date\n", dstPath) + return nil + } + + fmt.Printf("%s is stale\n", dstPath) + fmt.Printf("downloading from %s\n", url) + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("download error: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("download error: status %d", resp.StatusCode) + } + if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil { + return err + } + + // Download to a temporary file. + tmpfile := dstPath + ".tmp" + fd, err := os.OpenFile(tmpfile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) + if err != nil { + return err + } + dst := newDownloadWriter(fd, resp.ContentLength) + _, err = io.Copy(dst, resp.Body) + dst.Close() + if err != nil { + os.Remove(tmpfile) + return err + } + if err := verifyHash(tmpfile, hash); err != nil { + os.Remove(tmpfile) + return err + } + // It's valid, rename to dstPath to complete the download. + return os.Rename(tmpfile, dstPath) +} + +// findHash returns the known hash of a file. +func (db *ChecksumDB) findHash(basename string) string { + for _, e := range db.hashes { + if e.file == basename { + return e.hash + } + } + return "" +} + +// FindVersion returns the current known version of a tool, if it is defined in the file. +func (db *ChecksumDB) FindVersion(tool string) (string, error) { + for _, e := range db.versions { + if e.name == tool { + return e.version, nil + } + } + return "", fmt.Errorf("tool version %q not defined in checksum database", tool) +} + +// FindURL gets the URL for a file. +func (db *ChecksumDB) FindURL(basename string) (string, error) { + for _, e := range db.hashes { + if e.file == basename { + if e.url == nil { + return "", fmt.Errorf("file %q has no URL defined", e.file) + } + return e.url.JoinPath(e.file).String(), nil + } + } + return "", fmt.Errorf("file %q does not exist in checksum database", basename) +} + +type downloadWriter struct { + file *os.File + dstBuf *bufio.Writer + size int64 + written int64 + lastpct int64 +} + +func newDownloadWriter(dst *os.File, size int64) *downloadWriter { + return &downloadWriter{ + file: dst, + dstBuf: bufio.NewWriter(dst), + size: size, + } +} + +func (w *downloadWriter) Write(buf []byte) (int, error) { + n, err := w.dstBuf.Write(buf) + + // Report progress. + w.written += int64(n) + pct := w.written * 10 / w.size * 10 + if pct != w.lastpct { + if w.lastpct != 0 { + fmt.Print("...") + } + fmt.Print(pct, "%") + w.lastpct = pct + } + return n, err +} + +func (w *downloadWriter) Close() error { + if w.lastpct > 0 { + fmt.Println() // Finish the progress line. + } + flushErr := w.dstBuf.Flush() + closeErr := w.file.Close() + if flushErr != nil { + return flushErr + } + return closeErr +} diff --git a/internal/era/eradl/checksums_mainnet.txt b/internal/era/eradl/checksums_mainnet.txt new file mode 100644 index 0000000000..76915fc03c --- /dev/null +++ b/internal/era/eradl/checksums_mainnet.txt @@ -0,0 +1,1897 @@ +9c3f42e0247d5503533f437ada2d44e7e9661170421c1b7844687c8dcfc0eb9b mainnet-00000-5ec1ffb8.era1 +8a8337dbb190b27dd547827db62aed42fe9ef0ab323b6895191d48bc7c6a7127 mainnet-00001-a5364e9a.era1 +7da7be2b4b2f6d8ab8543b709928b71d5f3dfac080f82a94b7d07ee7f2adef43 mainnet-00002-98cbd8a9.era1 +8ca41709b2306a978f00e608f601741011b543c9d8426493c8f4d3d0939a14cc mainnet-00003-d8b8a40b.era1 +b73ad13560e80b13457497a2267e060c02a5ec4ddd92c8d3fa81954b250f7aef mainnet-00004-6e3baba7.era1 +11207a3fc5c0b392f296dfd6450813e9e994e71fbfe3076a7e050016fc617ef0 mainnet-00005-5cff5a4b.era1 +d0281e7b848e69f53333f1cdff1841f101d846605fa82df6e849a3b2ddeb8354 mainnet-00006-678fb793.era1 +8f38a986ac5bde04fba3f9cb1ab2b6b4053368e9051a8a19592f8785feefa01d mainnet-00007-d9bc682b.era1 +0ce07c95e68c29c3b92bba2025df6304bbe021d010e94fd47c5a8d67b519e235 mainnet-00008-12c9605f.era1 +3b0bebbf6e316dc61ee8eb61d36abb5b09a954267ed3fa86be4e8ea91585bc49 mainnet-00009-f9e4e890.era1 +9409cebf51c92bbdd4069908d419c30798efb61d88632d45dfac9509622e39b2 mainnet-00010-5f5d4516.era1 +6914841419be9ed0e35c2dc733d43d199d6ed592ffddc7f07c6b471bc8941e75 mainnet-00011-30f04eb9.era1 +3efbba460c6164593325d8d66b09b537f3682d93cf5a6591b34f1dad09c995e9 mainnet-00012-5ecb9bf9.era1 +469791afa1fbbc7e7e60948fa151908269c16584f3ff5bd046d94efba48b85ce mainnet-00013-d0175c1e.era1 +ccf29e712848407724b8a9b3df855bf9e8c0f44989bfce045261cdab82322917 mainnet-00014-4f92d781.era1 +866c17d2d4d590502f48b8e35a6335b56a4c6bfce8a4df2d18b0e8c6950522eb mainnet-00015-a47cb8eb.era1 +f340e23bb565d6e42d9c5c345b654dd281d696556dcdf2de36803c12bde59e48 mainnet-00016-9344d8b7.era1 +399adffc4bc8e72883018475d05c4f1ded482c1940ac5fdd57fe285a3c09c1c7 mainnet-00017-43963724.era1 +0acaa325a1115fb6cce6a96a47c5e9aa082ae2447962f2c371329aaaf577edd9 mainnet-00018-efce27b4.era1 +ae332ca6f2b9c6725280dba003445c3b7f0e7dd49a6e2e9588787457ba621b14 mainnet-00019-f5434352.era1 +ccb29a81758de7da262c4b5d42c902989cb00f27df3515dae247b831d2ebbc3b mainnet-00020-0c405203.era1 +0aec5d0f99f567ca4b1ca370bf02142b5552ff4845d8ac3a502308f49facac04 mainnet-00021-20d8f1af.era1 +e7f0f1567c1ac9c600753f24df65372150bc3cb4773bd673a69db7b0a2fa2ec5 mainnet-00022-b694d895.era1 +361c0b9d23d7befd5d1924c166f0ec0b40072c57c9b02cb4f764a4815473df6e mainnet-00023-11beacba.era1 +eb484d168d8d60b5249c9ec8fd270049bfe55d0775fdd1d9176dff1e0c062211 mainnet-00024-f216a28a.era1 +dcf2c651a68085006ea26f8b06f9038c6c4b0b8dc69683aea4fd72fdd32155ee mainnet-00025-987cb620.era1 +dfdcc53b9a99aae72aaa023b0a633f0b3d88fe5ed2beb445ba24e21a60c2c448 mainnet-00026-3afd50ff.era1 +9a2004c5d9c4040bcc5009e04a3ebfacc764773aad2ad3e009c67ede76c916cc mainnet-00027-28083285.era1 +821a1978eb350a7529d4ff62e81c2b5fc87c65b93bf9bf9640503d4d3a4e7abe mainnet-00028-362fc97c.era1 +11537dbc309b94b2c4b18c2ed6b9d0aeb79cb7f2bf792ea10e766dd3f7986bda mainnet-00029-a0cb99e2.era1 +c86c2efb18098961533aa58ca13ee39af4d4204767efe5cc593285e33b011c45 mainnet-00030-78fc5e8e.era1 +f6947b30494defb10b72e014b0192dc1dfadfdbc6cf740c59525fd76c8447b3d mainnet-00031-52306cf9.era1 +0dcecd1909ba393e6fb0905707fc1922d776d891d4bdc978a3cd1f9eb1818703 mainnet-00032-cb4d0c3a.era1 +fd1194994e0b3ed22d7c1809a2bd5233fee92b9f01684bca2f134b0a1c27e47a mainnet-00033-0c3781bb.era1 +afcfdca6fb1e7691ce9fd5d8b3f09c5105da96882ea9ba1c5e188964d40243c8 mainnet-00034-fac9315a.era1 +e46841bca92299fba6aa326f000a4384537ba481667149ca0846118ae6436c21 mainnet-00035-737e0757.era1 +bd6913818cface9f9bcffb0869a5edb290b9f760fc9931f0ac67eb7fdbc4da4f mainnet-00036-84c7c1e7.era1 +a2b34158951ecde2c770d5d488e3d1264d40b9090b2fe7a77feb5b79d65fe7d8 mainnet-00037-34d06765.era1 +98b8f1dab9c615c1b98f7b39f48da29c1352b4df8bba36d03f306b11899b1edd mainnet-00038-38aaf94c.era1 +8dff95e9cbd3df32923de8ba6c30efd467c18c4eb84c133974ae06d8890356e7 mainnet-00039-4ad4940c.era1 +20e59943d0d807fadf05f755be3f11c296dff160e72e714de7c09a5d1cb24c1d mainnet-00040-4707f60d.era1 +8d2826f8cb0da37875b245898dac35a69d6cca7c59763058f4a3efb02943791b mainnet-00041-a6a87a9e.era1 +95480ed8ca2d8669f0c359fbc4095b3e1181b7335f2232d4e19b3be21241d6c9 mainnet-00042-5c8dca3c.era1 +6b7450b614e063acc97aaf35ed92a8a89f14cb2d1abec4489be2106122dfb89f mainnet-00043-cb513d91.era1 +5f97400722b684df94affe98e34822a63c4b1469482be6f013810ce1fee9778a mainnet-00044-1c72a390.era1 +077c7a17334e560638d42a8eb3b985312f20a2130a344567af98798c498b27b5 mainnet-00045-a87afdc1.era1 +e7acc9e2f16b438ec8d0f4f897e597557613793c3184bab75456aac00adf401d mainnet-00046-22b3f78d.era1 +41731bb360547c1f7a0f51058f0597f8ed47a80daadcc87dc1b7fe3e51529934 mainnet-00047-92d84372.era1 +9cd84bd46d099a9c752f7f9eea3b40cbedd0429f60427b393467b9670b1a31d0 mainnet-00048-78ae53ed.era1 +97f459559429fd0fe8e2a53c069e419c48168ecfc3ca28defc2df4b3008e3735 mainnet-00049-3934e960.era1 +cf85c4454b9c01575a6e32c1b8892777fda66dce0c88276a0b6b6d57d5e953e1 mainnet-00050-71698ebf.era1 +8d868be1bfd9be49bbb4ee934ba6fcd4061d36ce288f52c2841868e98f8e7299 mainnet-00051-2c1c7778.era1 +1f2580df1e484cf4c7de668f36db08c57d5b59ac68757bdebec689a9aa3ff314 mainnet-00052-3a047d9a.era1 +09c39d3ed18b7222ebae1dd5744b2c197a0b8bfb6fecc2f885dddd44d3568c51 mainnet-00053-161ee1b5.era1 +3b6eb0744531dc25bd9423793f119aff7a4e9abb156e44a7959f761f6cd0b52b mainnet-00054-14074ce7.era1 +5e0f959ec3cf8437bef4a9143871350a44028597626d8089342dbc17189c2d2f mainnet-00055-ae639ad8.era1 +752eb0640af043828bcf854b85d05d158e7ca3687c87c1fbbe11545f5da0f47f mainnet-00056-d92c394c.era1 +1af48939e98749aee96a9fbf91b0f33df71f885e36b04bff3b188510cddb880d mainnet-00057-4bbe776e.era1 +b3a272aca377aa55f80c1dbffb612663ab396edc96515aea426650a04b9829d7 mainnet-00058-9ac60ed8.era1 +d9060a7daa173b9fc2e15cb6aff5c09f18ddf817d7ed85e1430de23a997858fe mainnet-00059-246c1b33.era1 +38b4cf15925460bfb4f26a6615ecf44eb8196178e43906c051531a34c18503ff mainnet-00060-4533d0c5.era1 +ee2f48f124bdee13de49f655e939bea610d8567ab1ed4db955e7bd0e64abaa37 mainnet-00061-122db1c2.era1 +ef4649a54302ab73f8d0db0a0f02d7adfb329da1e4b1149a136532411fbb2fc1 mainnet-00062-65505079.era1 +240f3248e2cdd82ab945709755536f245c915c0006cdad5a1ee0ccec7ea34f25 mainnet-00063-39b21911.era1 +36635126cfe521a3f3d1b3ac845ae3ad9fb492df8698a542c9d308d70f4a90ae mainnet-00064-db26a83c.era1 +acbd243e23502b01ff099d707d94b9d0056e7269265c63d19fb927f875be303b mainnet-00065-1df3a40f.era1 +d11eb990957f6c356a90ad5f2ca7bc476b4e623af20acdacbd0957f9e0ebf23e mainnet-00066-07bde22d.era1 +f66d3833b3724f6c15822ab00c60424e301f523693034c637898187daff42f76 mainnet-00067-751bac83.era1 +dc9359481ac2399643c1cfb337016ab1dd14acbe8e69138f29147eded6088a4e mainnet-00068-546a10c1.era1 +842bd952c402efeffdbeaeb592addd80dbac69e409be25f2f0de673beb574c3a mainnet-00069-55c236ed.era1 +69358acd86be8eb1bc8fc5f8d2d09a8ba95bfd44240b63999b342cab63b54bc9 mainnet-00070-0ac3ebb1.era1 +661cc154b17b16fe01c99bb533bc5480c548fdf5d739504ec1470615ec2577ce mainnet-00071-2fb03713.era1 +9c9377c654f4e8c88da31b31247e04e179b06915594b6d7cb24d14aa943885ed mainnet-00072-2f9a4a75.era1 +ee3a628de9e60f3183c61261e42e1723430d42a06b07ef8101a8726b1980ddf9 mainnet-00073-32871a43.era1 +e3bd37549c917ab6d82b6300be91eaed3d11ed8b0dbd0be9be260b4b48f23392 mainnet-00074-8aacdeee.era1 +44db8bddfff6cd79e3566e77bd383995218c7587f43c76263a315918a69e1d02 mainnet-00075-368ce2b1.era1 +03c6d37a2b6992dec4e0a028e51c1ab000ec97dd9899e857d63660d61b3f3f8c mainnet-00076-290a4131.era1 +9c696fe696282bcb09dcf0960b50e40c3438250ef074d1240d62a99864e61fe5 mainnet-00077-5d736b0a.era1 +8bbfe812605d612ad6c318836b8dc18046c6259db4324c7b0df1dd21ffb0044a mainnet-00078-98ac3e9d.era1 +97d6735bd7e1d332392be25adee20abae497cfd2b73be7dbd54c5536db076ca6 mainnet-00079-95e0734e.era1 +942b46166b52acf202c4220815b7076daec2c9a6f90921004dd09052dcbaf204 mainnet-00080-d778ae86.era1 +ecfd5c75eb61dd7612edceec5a7b54294484bc956596fd2154ad6005927b3874 mainnet-00081-2089ffc8.era1 +687012f0accdc5525d2522bd818d8780c5f13d845a6732de746b621b8398212f mainnet-00082-382ac3bc.era1 +3ff51981d8da4d2635d17324614b390628fbaecb300bfaf86f1b3d819c9964aa mainnet-00083-5ab1cca2.era1 +2e6094b9c31b6aeca3c4eddee9da7dd939398acb1259ed27bd55a042b2d30f2a mainnet-00084-9ec0497d.era1 +d3834c0f0ececed210279e0ba14e678ecfb0763504b7fc7aaf6652d059de6267 mainnet-00085-f847bef9.era1 +e378cea66dd39c845c13a33a5afe57d527a8c4fea40d09388fd99df831b28287 mainnet-00086-0dd5eb92.era1 +b5424d22adfc070d70b983d6a59bc208d3b69b84d5260672650bc6fca19be18e mainnet-00087-c0612d68.era1 +efe3c59bae8e561bcd27eb34fd5158fc447cbbccf030966b342c3e905ff6d0b9 mainnet-00088-3f433e63.era1 +bce0705620a992e73525cfcbadbbc637e9d5a6df0f4d1c11d6ad5c6600512ab6 mainnet-00089-0432ee13.era1 +d4e01aaa61e640bb49b8d0a7a54618fccec213a02e10e606495f8a59178dd338 mainnet-00090-cf23b0c8.era1 +86975356bf8e070f6a9e72d74a5bbb238ca01e91387646ce7d8f9fdb8239dbf7 mainnet-00091-9fbb0197.era1 +fe5bfb77adb766ad96c270897d1998a41b32ea747aeec107aeaf7963d08b2d0f mainnet-00092-f88ab15f.era1 +2bbd7abb11077c01143c952f183043ca7e791d0cf19beb848acccb02ffdffb78 mainnet-00093-b7499b8c.era1 +cf6d59ff853c33848c6d944a3e409d12b5750d4e675a21f13fa909e8ff322baf mainnet-00094-5c45bbb1.era1 +f30e125dbbed27f0595800330c2fe1ec396baf86439d0e9a9056ced6bbe9a989 mainnet-00095-a3dea11d.era1 +8ed14ae5ea4801411e4969ef98cc7281bbb96ce0d600227251b5e2262d04b334 mainnet-00096-91ff33f7.era1 +ec0f5896e06ee4dd845c5c8f4afd21f089e213270693c619b7f7418f396d62c6 mainnet-00097-8e4ffd2b.era1 +0d5c0acc86d6ac250db521e4e549d375a04eb3782407547eb1998d1a1a14941b mainnet-00098-4c5709af.era1 +1874a696a018e92d1231a988349899ab713c5fb363ff66d809e639819b951651 mainnet-00099-d55b92c1.era1 +7975244ba01f2c47fc484b54c379a88a2bb000d63142209bf42b89cec7cce1fc mainnet-00100-bb39d00a.era1 +2cd5c2b365bc770ab681ae9fb239434dca9dc9e9313608d7248c2b789705749b mainnet-00101-e6df1942.era1 +473cca4df9b620773192be4e474ae7aadb2246b0236d80bf7d9cebd8987e8617 mainnet-00102-2aac9e21.era1 +b5b81df30c8e682b446eb08090701b978e9dd15e8a121854b01233f321fb85f1 mainnet-00103-3fe56c2a.era1 +28e6861bd1ce937c7808b5d98807b644459e9529a785279ab8288e4fe041e9bf mainnet-00104-f3269b30.era1 +71bb327b8b61e9a7146dd5c947cc24a3e1f05e6aa0fd444663fd22583bc1c29d mainnet-00105-6f2f86e8.era1 +db9b1e7caa3135a81aabf36d5bb18ebbb57ad7fba5e1b0933c77fe5bf840db8e mainnet-00106-621a2527.era1 +a5e6534639f5a61d2379c44ee0ca47067a8301e0ac66533825abb4b1b356766f mainnet-00107-c3e8f7cd.era1 +e13b2b0fa20c89fd295db7589860d05857364952acae4b0ae5205ca585f6234d mainnet-00108-be1a1635.era1 +b262e31da0fe5c9b4d93cd8d685ba2e93c9677744eac361907cf6ce9645c52d8 mainnet-00109-49424c3e.era1 +380595c5f65a25f8d807fb325d58a6f00b8b3126d9de7be76d83a6c03a4fe71e mainnet-00110-af29e604.era1 +33a817abf2e9ca55472f02a290c4fc943f022addb2ea06b5571488257e05c8d7 mainnet-00111-1738246f.era1 +51ac6063c5076cb5176fd5e53473b73cda93b5b04bc8df917a9fc47478fd2a33 mainnet-00112-0074a32e.era1 +124cae748ad7963bbcfab0425450bf4ba224b61537324083e4f75880cac8c5a2 mainnet-00113-56e19130.era1 +cb12db25f4efdfaab5d7eb589edf41a144572f53e7884ab8955c0d31e69ae8fc mainnet-00114-10c2a569.era1 +f15a30ef45c74b6739f224f74e8d6f991cdeb692053a12e2882089beeac0f884 mainnet-00115-26efb6b7.era1 +6dc15f7f578b5c2ad9ae38952113cb236e2d56ee1c5efeab93ea00ddb4a869f9 mainnet-00116-bdf3bc6e.era1 +fcf289c4b3126aeb3187167aa2210f8feb1daf018c623955524edc2164f939cf mainnet-00117-e68e5334.era1 +10907ad560d2f6355aafff4b32cbf197971126c8e0aa0e96be7c8c97b241aace mainnet-00118-1c9a2437.era1 +f335c97001169b8d2068fc70067306bfe92740eb101f15b6700c55eb09ef2304 mainnet-00119-5fc6b689.era1 +37e6754278740f158e8a5220e649000c499cbe5ad579900e598bfe0eeca1785d mainnet-00120-cfefc65f.era1 +fc7d276a531ad1ab2cdd14909204a97db745345fe1dc66801304d9d6263b76df mainnet-00121-0e29b6cd.era1 +e003880ddbe6c14ec8993a141b7d03bd7a94c535f16bdcbac2dfd221d20c17ad mainnet-00122-cddbda3f.era1 +b2c7bc85c76937b4d5e8f03553ff02ca12d76e8631346bda57042bf2652c217f mainnet-00123-7717d395.era1 +020aed308ebec19fb1e688f4708c177ab5c36ea1795db2a8ba77afca97e1fe3e mainnet-00124-2e66a66a.era1 +4d4c12d854a2f5e364f5636fa5dcf69e8b0aad416cb4f61e8fb63bfbac076e7f mainnet-00125-82fdaab1.era1 +8fc7016bd372baa22614741a4d6fe2417e9b807931597c67e256e8586ffed7cb mainnet-00126-427637ff.era1 +9133009a71e9a524744106fda96e8a092bbe8488a52bbeb108ead8dd45f621f5 mainnet-00127-65e302f1.era1 +2d1e305a6693b93a47f8d014cf0ecc78a1eb9246aa4a22af689d75b7f855e9fc mainnet-00128-6fdc1fed.era1 +7b283541ad76e10929e2a2396174a776707234ec70edbdfc1a5129764c6615bb mainnet-00129-c8705b6e.era1 +5a96e61a62fc166db0e838b619f31b21edbd5c097726fb72659a2dc0a05e60a3 mainnet-00130-650f1d51.era1 +7a60d78f969174b20c7f00907965f9237fefd44bb8167c7d42a6b8647b67239c mainnet-00131-7b4435ca.era1 +cf3b648a50a3ecb1514819701a6ddd345f456d58fecb449d60d4c8439bf5b9ee mainnet-00132-23bd7603.era1 +2e2bcebed27256595cacb454f47274301d71e25086e992e09b740b5b7fff7bf2 mainnet-00133-c0faccfc.era1 +7be5c210f2dbf15457ca97b836c252ed4113ce2f8b794fcb1857ffa5b6475d86 mainnet-00134-ec9cf3ec.era1 +1379ae2244ddcb1a026bb9b04f26abc1687a79d82a71d8c196da1015b63f904b mainnet-00135-66f5486b.era1 +c072dcc6a7c5b27929921034fc0cb96d609e528f614efb97daf59d9b848cb322 mainnet-00136-dc4ebb94.era1 +a8570851f92ffd33cb8c44b4aea130a0a24cc8d2418c9cb32cfb05d0c7865ee3 mainnet-00137-02298200.era1 +50faed8730fcf592ffbe1ffe8bbdc1b3c8643704bd419a8c9bc33c4edfef9a63 mainnet-00138-3d231400.era1 +939ac8db4dc0b0c27635e986257a2fbfb8ca8aa6a45f2aa22ebb39591a57a3fa mainnet-00139-5f316611.era1 +7e84c2ad1da194e20c4533be1c297a2dd442cf829aad1c99bd9cfdf8b265f576 mainnet-00140-f13c9fc0.era1 +6830c25223962969088b4d55b1cc06a879dec452695d582e45b4bf74387e141a mainnet-00141-17dbb0e3.era1 +3665c541116f9563aec1cb9454a4c61535b681717d34ecf9c8de70d53053a38d mainnet-00142-e42539c8.era1 +64cd17cc860e99b3efa89afa7943ccd894227ff2dc31687936e64b86c4f88f7a mainnet-00143-5594a813.era1 +4eca366cc00e4ff4d5cb240b91fa84c54fe5a82632b6cfe66c776139bc2f0e0e mainnet-00144-5ac2296f.era1 +e30191fbb8fee15c6b844a4b806271330259c7c8ebafa9125690c17b400a53f3 mainnet-00145-9244d418.era1 +84fcc41d9252fabebab8254ce6c518a93ee3b50188adcb6b8974c9607323d4c3 mainnet-00146-af9e7a53.era1 +e0dbea3796018c40c3a2297d804d1944b32284eb8050f2c16004db94ef0c9c43 mainnet-00147-1b6fa332.era1 +1f1d4e7a4f95bc6ea9b5f606851fab7ce9d688012212c18ff4042760bfdf10c2 mainnet-00148-39f0b057.era1 +0742f38779b0fdba8f687d428e4a1ec19ade71c079259c29606ebc6afb858947 mainnet-00149-586c4a91.era1 +56157f687d849c562eb1e704e7d2265e774a5701a704b6cacf3de140d15f96e3 mainnet-00150-3ff89a4a.era1 +18d55523deb34917db5212e0b025a9249e416b8a6120841e87507e0eed3f6435 mainnet-00151-e322efe1.era1 +e120aa74fda9cb3673811d00e7c5fdb64155845f9979171a3e4261b3769c84f7 mainnet-00152-4d9d0d1c.era1 +d1d327c715f83afcb574518c842c93f7781a3e18192d8c0a052868c743540f4a mainnet-00153-6b5702b3.era1 +38bf622cb23f04c237b3b780cf5375ec519a06e2270648a9d61da3af009b2567 mainnet-00154-13608c12.era1 +d00300907afe184f2df7c6176478db881a1ef20d8fe4f7cb976f63c83edb28c9 mainnet-00155-d0bf6ce2.era1 +776f7f6d327c12164ceba5dfd7900edc73cc3610c42d162d6cab06d960bc44d4 mainnet-00156-b8c3629c.era1 +d423c18e2ccc90db5684073b77f4b6530b17b4d0568d2d4e2aea6e60f7b5315a mainnet-00157-97351a9d.era1 +660cda8c979fa567c1be2535a64fe1f1d2b2ef221ebba4a2c8fc697f9a1707ac mainnet-00158-5cee8f8c.era1 +e9db5574fd2a08826615813364d816b77988b601afcd3634bc9cd542dee2fad9 mainnet-00159-b92f84e9.era1 +d460f1142d881241a5ac03e07e55611bed45b979a85a84271448b39bdcfbd797 mainnet-00160-3e41d9f5.era1 +e198428126e8432e99a3821079a701ab8400b64919f6d6c936bc404e1846c198 mainnet-00161-0736b99a.era1 +5566e30ef4b51515d26b9e3cc6d7167f5f3ed4fab0b463ffeb8e49b2c859e15e mainnet-00162-0a1530da.era1 +90d71da92883bfdb64166a3b06b2e6afc1afa93241a63b3b19205e806fd11217 mainnet-00163-43212d3b.era1 +6dd77d7250267af09559b1bc759d48225604a3eb5dec2f0ce4a183e42c0ee8ef mainnet-00164-3744a01c.era1 +a976c82d9667b66d86b3963537270ecb412dceb859d34e6334977c7411752e81 mainnet-00165-3d14fc84.era1 +8b42ae6ddcdeced9a4a12fdb321ef07ec07cced26724b21e5b5fbc7be50e0393 mainnet-00166-97c25925.era1 +7d64711e3c5fcaf098bb3110ed93487038cce4cd4ec002d90461fc6cee995f77 mainnet-00167-11485002.era1 +c76e19eeadcd672c5896d98d55c5599bf53bce667d09395ba3b013551581d0df mainnet-00168-88a365fa.era1 +76c17d3eb82334c5d208d0c6a995a0776f71009bf9797ed5c3c73e7052077fb1 mainnet-00169-f18242e7.era1 +61b9bce113cb3d426ec6891927430859f97f8efd994b45399f40235bad94dac7 mainnet-00170-f03ea8ee.era1 +4a0d46d3efcdcc98c4606f371017b8dbd9ed0d418e70d80bcbbd926353f3a5d4 mainnet-00171-bec8ccd9.era1 +7c906d4fd5bd1df403a3a340f52df6b9a31d56ba098105217f69154a7fe106fc mainnet-00172-34a4c5d2.era1 +2a7d767dd8f37b8de9b52d6593a4e322e7993bbb18f383a8ff1fff0214bb77db mainnet-00173-e1ae6c81.era1 +806eec85a2df1d7253dc9282a1d430d3f2a898e8fae74cfdf25872c8b57d4718 mainnet-00174-727d10b8.era1 +554840bd4982cf792b3439227c38492f601b08b40e1175c347ffdb52e1894865 mainnet-00175-1bf21dcc.era1 +ca8d89eec998fa58a128a64770137273ed7d11e7d47454f83577aad42b9b57b7 mainnet-00176-ecc872aa.era1 +5034d99d013c2b173c1c98794b5e8519657d6643ac23a0484763bce3a9aae210 mainnet-00177-966bdbf2.era1 +5100933799b61590847d3279f3e8d52ae00c6a78a5bb0f701ee9d582d270a01b mainnet-00178-b412f22c.era1 +8a28818dac4aaf5f8bb8d7edafcfa2b9672a06c36206a3110737cf53bfce4fcf mainnet-00179-09e40d3b.era1 +bfd6db13cda398fe7c80b41cbd770931dae78a0292d2b06ef572bb89d0718615 mainnet-00180-8ce22357.era1 +2e207838904ce105993d9528173ee48771ffcade3c28f497c3eeeac772af6f58 mainnet-00181-ac1cf418.era1 +66a64cfc1220caef2f49667cfb6a4c7b408e470da598caf87c50abb2217d133f mainnet-00182-f770e12a.era1 +2b1235b5dc35872f2178caa60a2bd4bdc72913509955d79796a455f8a22e6ddc mainnet-00183-798224ae.era1 +7ce2dfe40051314987fc3b1204da6d9e721b92c2f9df0a12facfcec00435f6e8 mainnet-00184-876fdbe5.era1 +4647b15e4799dfc87cdf931cc5025c9ff92b43cdf57e25f9b36c61ed1688981b mainnet-00185-7b447a76.era1 +5040f826c205e038873b66deb1fb562b60a9c8cd6d7d264697663fab3d70fb70 mainnet-00186-f1e11ac5.era1 +3c1a5e911eb86bd1813363194cf963c9b7d67c6ceeb15cf86ed2d7172eac5ef2 mainnet-00187-ce8b009f.era1 +cd03d04eb762ec7a86ff476d54985a5b47561d1cfbbae14c6bbf8462ce79a528 mainnet-00188-c7bd816d.era1 +e302ab30c052d1daf7783a021af19c1d394049ba4eed3e3bc33c559dcaa4b622 mainnet-00189-144cc97d.era1 +d2dff17507620e705c50040cb45507d9fe83f488945dc10e9e0d4f508647e71a mainnet-00190-cbbcca51.era1 +626db8c8972a26c290b5fa6441245db68f2eb6de7e41b90d6ab214ef44909359 mainnet-00191-3a7f6484.era1 +3ca721781718361e94fa2d011b37cb89d8477348d4ab7d99ffb32af79093d7c6 mainnet-00192-8a4639c3.era1 +8350e06f7bc0831e6ac2184cbdb8603177fb3184b092f4320e470d521579a78d mainnet-00193-52629553.era1 +395802fc385c14d30e2a3da26eda066ce93e64228a3564c85aa309fd0c1f9727 mainnet-00194-c4828a4b.era1 +32b1ce49f1ec65ec06bc5dacf8e5a3ae3df4ac6ab46a0e0b74a79440f652e0af mainnet-00195-f50a165e.era1 +0ebe874ce10e7d9459b55f9e9743f72634b89b58edf4171389299599654d348e mainnet-00196-5c31919b.era1 +0a1eed2cf5a71cbfd0c969bf11834cf637dd977ea81198f046f7762c7227ee46 mainnet-00197-9e2a709b.era1 +14b10d6bec29dc751efc999b3663f546e6c05d46b48ad666786ee03e81706fb9 mainnet-00198-c3e781bf.era1 +f93ff7cfcb2a47f5e3798db2f74446635342b92b21594f1c91bd800346ca69d5 mainnet-00199-20c05ee3.era1 +7fdad50e2fcc986cbe27fd5aedef822fe1c5bc43d8bb0a733d86915172c21746 mainnet-00200-dc265ad9.era1 +0c1a1efcae99cf65a0533ce10085cddbd081ae80c9ad6eceb3e16301d23a5810 mainnet-00201-1356f2da.era1 +e737494f1c4188a3aff61ea510d3791bc14c5ceb9ec2bc81bcaf560f86de3b48 mainnet-00202-84e86114.era1 +b7e1d6cb3fa829ab59879425bd0801dcd5134ef4d45419a62623e5b74db8809b mainnet-00203-f2da7b50.era1 +b05ff70490032070dd3d02ec0170b9e16881f25a466909a738a8f58f6c3ae51c mainnet-00204-7f42b43f.era1 +bf5046c68782b52fec94aafc863a592bf9a7c44c347ab0f5c78fef14b61d91fa mainnet-00205-afd08f8e.era1 +0f8ea93ef10ceac74ea516129006b69651a2abbcb129366d947fc49dca8523e9 mainnet-00206-cf4a2c65.era1 +dda172ad37c9db5e43fbeaaca0dec05d3673c55ed4c5f9b593d8c4862f7f1027 mainnet-00207-59a0e883.era1 +e157c8d46379205b6bec2f49189ebc1f9bbe0e2b361c1068da3ce32d2eaab797 mainnet-00208-3d0bbaf2.era1 +22ee433ea64f0e857171e10c904f0d190c6d9c43d037e5313bd49ea0cd1d05b2 mainnet-00209-c1041285.era1 +26c3bc51f0ad7320b02448db82705201257274f129f899b4b15e2c4238dbc2c9 mainnet-00210-1eb673ab.era1 +467213b7bb251a7b51236a357cf019ca1691c86d65116ada6b2783867bd2e9d9 mainnet-00211-01e5a4d0.era1 +431217d3ab4dc0c5566e3e98df2a38a4b34f05934757090b72362bc3035909da mainnet-00212-83c3bb0a.era1 +66346ececfbf29fc572d85d6019f0e7eb76cbfd8d126d2a5f7aea7b2547147bd mainnet-00213-9a09fe68.era1 +e060bc6dda403f94b5029601d9e698ff1e73c6f8b9978f235f02dcaf3ab722da mainnet-00214-9e78dc12.era1 +319c9a5a2bfa41e06885002611873b156828815c7d2761270e7f072271cea80c mainnet-00215-b02bf96a.era1 +746442aea25eaa0f243fa13bf7bdb37b4b3e294e65a0c36310c17765e5a9ec74 mainnet-00216-209c8b32.era1 +399c317a2f40ae90905d2809e9e5eb4dc0ced9f19cf2fbfb3fa5e2d780e525ba mainnet-00217-6c84f49a.era1 +c05d0562e2c800f77a14dd29201acdc17ccdb06c87b88f5027135f648270ff47 mainnet-00218-acb60f14.era1 +fe740d7ec3f43c228bd39d4bb8bae8526c7cdc747062bab8954adb6da628a1ed mainnet-00219-0a773645.era1 +5409e1bdf10518d1cb5d9f58e70d07bc5313f969f7dde1e617cc0af49a2ca834 mainnet-00220-76ed2324.era1 +2880b0f5c23c49e79e498751975137e2a9e5ce89044560636ef16060e241ea6f mainnet-00221-76ddd2d8.era1 +5f03fc4b387d079e32f314b4a352212376fc6551dad8cf210e40a36486130b65 mainnet-00222-71e986b2.era1 +1de0c6bb2abc98fd83fe626070d64a7759bd1561196587ef462d357751f4dffc mainnet-00223-ca2b5c28.era1 +4fe9e7d3fbdac24e845b4945c9b0ed046325c67b325cbdb4a5222ecb9f71de96 mainnet-00224-ff571e13.era1 +69fccefa8e7b4cb53e1aeee876a2bf6f644a685a18a2bdc5ccd1f807769a9cb3 mainnet-00225-1cfe3239.era1 +1d551889715dff2276ef1cb3d28b94ab84debf4577fd14509fdd433d20016413 mainnet-00226-b0eb8f2f.era1 +4d9f29c9b439494a0f377979c76d6f47377171f3de0e503d1732b12e31a188fe mainnet-00227-83556e9f.era1 +70d7125b225f523943b79616af7cfe6edf5cd20621f321e7ca894d73a2cc77f8 mainnet-00228-7651e7fb.era1 +be32f18cfe34a4e6187f87fcd4e6e7baa10778971049f8a34f40c77407d88588 mainnet-00229-238ed788.era1 +d901af617491c36bc121e25b0734a3c7a37496e6a3bcd03d8d09cf717eb57e6e mainnet-00230-3826affa.era1 +4ef61acb4b95445cc7a8ab5105aed016fb35f6ba9a2154d382eed203dba33279 mainnet-00231-b81f93c6.era1 +d506f9275e552aab49cde4e09ad5499bea5d8da6fe6483c83af627612f6218a1 mainnet-00232-0cda2a75.era1 +8c0386c53e59d8363e4e73d68c1a9fe124c61eea8c72486716600649d59927e6 mainnet-00233-b183167b.era1 +1e4702b597a06209d7821ead4405160cde6ad37602df2f68eef9167f6a5ecdbd mainnet-00234-4a88300d.era1 +34acd755492f89d62ed5ebe484aafac11f8577e7d10f71ee114f46cb84bf21f3 mainnet-00235-05ef6143.era1 +fa336dadad7c7c12a720641ee21dcf712fe6faae02819944772084a74bad29b1 mainnet-00236-4164fdf4.era1 +293b613f1b39810a965f334d4b68cb5930758117659ad5e8ebde82bc8cf05887 mainnet-00237-d5c9eed4.era1 +725bb2261ff58b71cfffc9863e1871f74c07249fe542515560f4e5cb58a35b7e mainnet-00238-db0d90c5.era1 +4db568aeec1e45cd5bf9dba0c284a40b303a50d1d6fce44f44f41491dd3e56b2 mainnet-00239-a0c972ed.era1 +c1f65805f6bdbc48c3059859e4d32796778cd4184f451f035baea8e216f6b597 mainnet-00240-9cc1a86a.era1 +e24ea67de4ff052b3dec75ce1f868e53a40187949411f3995cc2ab167fe51347 mainnet-00241-8ab5ad43.era1 +5c3f0b5e946c42fe19348ec73bfe7fd4c9de5030f02539b235aa37056bcb0a93 mainnet-00242-491f232e.era1 +0bfe4e75b28f738ba47f5d3ca868b44f57d66173bad19b375eebe9cd93816d7a mainnet-00243-f66eb348.era1 +536be6c4e4b85b18244b4ae7831faccd98918e60f8cf371846f5278f5adfddcc mainnet-00244-7b141f13.era1 +395e73f999f92c6934129b14b10093fbb556d30eebf794f858d55cd4bf72a821 mainnet-00245-ef5b96a5.era1 +ec7ed2022fed7a83624a665612a4ad0bb69d8a22ac9b851a6f198b42c495ca5c mainnet-00246-32d63aa1.era1 +dc5a26bca0d024416229caf8f3e21afdeae726e117fa858e23c6db533b28f583 mainnet-00247-7b033a6c.era1 +f325b28a7f1015865b5bbf20ba2db40c13109af7c1a96faab8c7e91591a57703 mainnet-00248-50916052.era1 +157805c7380f776514b786262f29295a798cfda5669d2feaeeb7c99d36175763 mainnet-00249-75e0db34.era1 +a9bcada73a1902235625eb43b828c533648ae862999711691f8c6b67b08bbd14 mainnet-00250-4781ac7f.era1 +657b73cdcb86e43603efbc2625b449c526c501fcad055b5072e845d96d6f4286 mainnet-00251-c0f8b33b.era1 +18fdff48e3ff474f39a595eff14317d5bda72dfe6e113f880ee5444719e7168e mainnet-00252-afa72ca2.era1 +cccf5306905b1e2141db3d5dbdf994e063e9d931e607bbc2f0193f232e076461 mainnet-00253-96c6ccb3.era1 +06a86243f76c00c63bc9296cf01cc35dc6e6c798a34c76e5f1d8c95e814e5090 mainnet-00254-7b32050e.era1 +5ffcfc2b084ab71d603f8f07ef9ac9b48945e310b46009378f97859a7f14aa17 mainnet-00255-16317cf9.era1 +5e8b0f5d502a41b4a7220cd2f8b9257446799e56a20c3654dc3cf67e9e528839 mainnet-00256-b4ccb50b.era1 +5f4aab770a331de70119302d26cdbb6b1bdcb593738ee436b00c22cf57df740b mainnet-00257-98808d16.era1 +0738e28ea91aec4c979ba9ba8b5381513c3cc01a01306c4a33410c55a4cbdb0f mainnet-00258-3cf61b1c.era1 +fa877be3381780ef3b4defe1e4a98c89089cc78b4c4910fc574e2b7708b86699 mainnet-00259-051764d2.era1 +09aff4f954451ba6e19705e27fe2af7a9d2108310184a5ff60d83b05b35b9351 mainnet-00260-3b0545e8.era1 +258032efc35138e75bfd888ee5665d419e4ab1f89548da1cd0e27066bb95e693 mainnet-00261-a6f4bfca.era1 +eab73c427116a2759ac62acb104d127f2c4672f53118752caf08e4a540ae9ee5 mainnet-00262-1a75662f.era1 +4c16ead662a9731e092d0f1ce5be5df0e37b422d6c1844e6f853af2ec709a219 mainnet-00263-21bf7eee.era1 +0be7714626e9531630df7740b159be925eef22cd9a8243d745594d854ba49207 mainnet-00264-d41eb83d.era1 +ea30083769d810c1cfb254c52b8d691e810921bb61731d9372f093fcee0c50d0 mainnet-00265-e7a19561.era1 +934ab681e87604eafbc3535dea53b1a0d98480236d09fe022febebd53a67e407 mainnet-00266-4f172aab.era1 +5831b78b87a3cd549f3dcc891b40af7b88b983a5d50431d971ed25984a8f963a mainnet-00267-7c0e1bcf.era1 +2b562646da50134fba39460cbb0544bcf91b1784162a1a837749228fdc0ccbe6 mainnet-00268-c839e6d4.era1 +5878d26fdcd2c89bb5ffcabdc1fb73648a608aed48a644fc3bf093c8ed88d871 mainnet-00269-9ec52dfb.era1 +57cce61c6d0571b2fefe353bea1f7b07fd0cc6150f9c64418c54347fa3cf3842 mainnet-00270-4e8bc727.era1 +864afce33474b26425e22a753d92b4e903ef354c225d4c4b8e4368df5a456b44 mainnet-00271-5294c75d.era1 +e288f65b7037d78d48c7050c9796f285c215c17f5774624bf55334e2c609ee51 mainnet-00272-02a11db2.era1 +031dc92f73528d0245e3c71a145f04515bf797d63288c11c6e8138ea13505d80 mainnet-00273-d81a2c41.era1 +03a56b01a6de3a402af96dddf91a491f759237c1da99e42bd200bf43c356b525 mainnet-00274-9c4bd87d.era1 +74c043d4703bb1b795b7f7c3d5f280a30af2d35e9517071b045603f31bc4e6cc mainnet-00275-85b9c67d.era1 +809bbf2e67ec7872c95391dd90a4afe4bc769f0027927be382f3365e31620a5c mainnet-00276-38cc1236.era1 +677387a3f7f0bf084e41b0d7e1fabf82a56ddedf40b18edd5d9856e9000eb5ac mainnet-00277-40c70f95.era1 +0a838d463deec9e5c5b85e18d8725f183c2170540dd9f54e75d69b06c57ca23d mainnet-00278-d9e0d738.era1 +ef9c97d47691c727f714970dd4a9947d8143e09e5e25eb872360cc16e8ea9364 mainnet-00279-d20a7b7f.era1 +a622740738e04a5e673ed21192fa94aa81ac2e81dfd348edb8f36cbeec1edc58 mainnet-00280-54a85faa.era1 +6b98f2e6d1a839411148692305b86ab30240faa1343d1bb8f27bafa37cd9f634 mainnet-00281-f08b9749.era1 +6abbc1880218b1ba0c4684c4c0769c98b26545c41bebb0c4c388410fe7b26a2c mainnet-00282-a5912776.era1 +78dea83c37faa03f9d03bbb6b23101bd072dc512a8976a19b2f032c43e0a0d8a mainnet-00283-8ee7ec35.era1 +85407f624d764cedca0eb875a5d18f0cfa87aa060c36841c94537b02f3602932 mainnet-00284-374996f2.era1 +b88c6c1c9bccdb5b8f0d0fdb5d1a2a24b253f5f8e465106d1c6a8e6abc70684a mainnet-00285-94942585.era1 +8940a7e96a2c2c7a40a18f18a93118d9a5c41dc0cb7ad11f64392f344e028356 mainnet-00286-6d47a234.era1 +df3d4819985088b642837429800af088389b479843e1c99bc74e2bad652dd717 mainnet-00287-f9804151.era1 +cc8bfc4ee1ce288ef3c6579391179890995660ef78b36328b8c989f4da8d7ab8 mainnet-00288-3724a8c9.era1 +bbb4f0963dbf87bbe6c0ae49398ea9713bb8ebbc6103922bca89ee4c7251767e mainnet-00289-60d72bd9.era1 +4a9f3162be5b9e8e12186454dc4d64c34d17a78d8a7e51b9845bff538032e229 mainnet-00290-64cca80b.era1 +667cd9a0e715eb9476b4b0750bce1d729579e1040833c55dd45f172224ad336b mainnet-00291-0dfa92f2.era1 +fbbbaf9d092c289e437648ce030aef4d0bfc48bd01ac88cffdf4288a190f7c5d mainnet-00292-94905988.era1 +b4db0d6ffe70930e6c4a83fb787c3662fa7bf1782bd2775f791190c2eab9558a mainnet-00293-0d6c5812.era1 +ee58661e70728f41d969f9bbc2f3813d8524a8ae5814d2d6c9bc4098330c92a7 mainnet-00294-f6c5c94a.era1 +e9b226a29d2dbbfad666c14988ab99f1b70dde5e98366a667d5951188248fd58 mainnet-00295-4efa78d0.era1 +651d8832de7b0aeb119ce650914db9960bd5c18c49fe3db8d19e289787f749f8 mainnet-00296-81c1446a.era1 +1e65186f5a9d78ce2e9a87c49b734aac341c81d33ff638ccdd8cfb68e354d0ca mainnet-00297-08d13a31.era1 +803bb2f55f8c75b7916d0ca02b4e41c0a78a7f196036315ec940f554fc6112f7 mainnet-00298-3d1d6d89.era1 +5b88575c8949f5919df6f84f5240e4615ee3523063e149491e817005eb88fe99 mainnet-00299-23728d43.era1 +a69c3443a1142f5550e19f97c5b002fd6eed389fc3a788df1d598cd5d1985db9 mainnet-00300-de033253.era1 +6900304acacb549a91cd1a8134b20f996af9743da1efc554e40d6422a934f21a mainnet-00301-15a24df9.era1 +f6b8bb0f46957fa47e2dc210605e0631891f36e90061a1919607f01f6105efce mainnet-00302-ba653536.era1 +be87a729cae74d6e5493425f1363ca3ebad2d5b62f75f9e2be58638408ee7a82 mainnet-00303-35fde006.era1 +d5991b5894638d6062dacd21d764ff0c25989b2638544099d1af8c043f94da28 mainnet-00304-377bf395.era1 +f7b46b0af17d873ff5612a8eca4d7f933a08b39201a934a77724f86d86eaefa8 mainnet-00305-340a0b81.era1 +11c7324dc37122afb9409f009374c0b4eb62e6eaba1cc9d25d64ba523429152d mainnet-00306-848e3d92.era1 +e27c325de831974697c9ba15564c9df699cad55868a3536569e04bd37b71282b mainnet-00307-a3ff7916.era1 +ede1004132d35682082626bdcdcadf7df17182b94ff13923ecaa5a4f685dcbb0 mainnet-00308-48c7160c.era1 +6a338b7a5c69f50556da5495e9d26b74f7c3d77aa28200058f21d2b85827431a mainnet-00309-e7948131.era1 +890963652b631abb1981f98de7dec943f9e6dbb70973c71f01ccf5aa4382f2f0 mainnet-00310-db22eaaf.era1 +94c3bf7e8b977816736f06d6f8204a3fe1ed17ffd29d4d311be5859d9a7a8f2f mainnet-00311-f9e4fff9.era1 +53ea643472d4e5faff5137a793d106b285235a24d6e3cd6ff4bb53e72ab3afe2 mainnet-00312-d95903d0.era1 +72004650bd296128b8d3efefeecaac923a16b86989304110adebaffc3910aedb mainnet-00313-73f91876.era1 +281fb5fd464478f53069670afa53f68922d311bcbae6c660e738dd5755820fff mainnet-00314-8e339794.era1 +a607be2c022534077226b3a670db8d295344a1e57fcb831c89d2ba92a178893f mainnet-00315-e83123f0.era1 +e6df2e86fb6cc688529e4371ba198c1f250faead7f1b64b5afc885f5b8805d0c mainnet-00316-e49c7af7.era1 +87af67240d12f602175519be1ec4e39d5e238b5db8e4be17c8e5f939bbd02cf2 mainnet-00317-f3ae6a62.era1 +8c06c1bd3ffe05cb3b70a1a3884d3a9913eb9e0d80acce9ee2afe8b231ab8926 mainnet-00318-4bf5c84a.era1 +bed2444997d93ec16706cd80684c77ebfaf53b539280f2d2e3059100fafbdabb mainnet-00319-391837c4.era1 +db0346a2558c7181fd86d92dd4b55188c6b6e117fe3c422080a8a2bc0a850bfe mainnet-00320-bfd4677e.era1 +5ad52159859033d593d70524cebbd2c6781ba33276acbd710aed2caa93db2a4b mainnet-00321-7189f496.era1 +e0a05a81ce6f08de0398677ba3c57762e6cf03b68f0bb3a9c5738d2a1db8a8fe mainnet-00322-344663aa.era1 +f2a0ed15703130b139fc81bd88f561ff67b44c2a95e5af376fcbfd0b6673e1b9 mainnet-00323-e111bfc2.era1 +b75164f946d2a1aba85c9bb1fceb68740c19b3d86324c98ce93d2294a8653f09 mainnet-00324-be2b4b22.era1 +48b8e615992d0bb139cb3ee2776783032a2ed1a04e72acd85a785fd837d09c82 mainnet-00325-441fdc44.era1 +6b3575d54eb17c3b631e64d737b5e58787b2239e514eb84e15f8457cce72e13c mainnet-00326-42979360.era1 +f4dc8f39fd7f2172169c8e6f4766b4a09c7904db085fae98324b6329face3cb2 mainnet-00327-820afe74.era1 +abb852aac204091bdf380e6f20f1577d5307f0c9f70d3d885df4771e497d2201 mainnet-00328-08665862.era1 +d1396c5f8acaa5469f394522e8408ed3e7ae816a6ea8e7d68fa6ce60d9ce78f2 mainnet-00329-cc85d0d9.era1 +2be3f4490eaf2fbf8631b643bc34da2d2b978f2b24557e6e34e42096a1269c89 mainnet-00330-8ffabe96.era1 +b23f5f857c96c35e5d651131841eb91bd10d96d2c1d56328b81eefd51752201b mainnet-00331-57c9aa44.era1 +b441204d73f9484d12e5bb1b81d2068fe2a6e4564654e9f8827b258e0212b5dc mainnet-00332-3135b734.era1 +ce17b8b868abfb2b3caa4be81253c778fc6f89e672b0453dec2e68a930568edd mainnet-00333-ef368f00.era1 +579f357ea1096016184e8de024d8ac499d4317f027680f06d2ec4af955d5bd80 mainnet-00334-1c3457cf.era1 +972a808e6f0242894c9f2677e8c13fa78f3b9dc4b0402a1350f3fa22385b48f4 mainnet-00335-b191a95e.era1 +4b15db1107f822a04b34cb9fe6ad6fe5ffc7b203b11a4582d3edb8a905883883 mainnet-00336-b5318d5c.era1 +42f60efa2d09ef0c09429abc092a6f68ee43ed34f00c131f2793e61ec06ac0da mainnet-00337-a84d51fe.era1 +6e8ecac55c2621f7ec7f985c61b2ecd820b6500d3bc55db1b73d9d61c7011450 mainnet-00338-f0b5744f.era1 +669dd0598d4f0b1d845c56e186d3b6775e3a3a68616dc943f3542e6d6bda00fd mainnet-00339-5a637c4c.era1 +b7c2a9105a97e7c45c2d8f6832beebc7ca09d072ff606298072558eb14fab8c1 mainnet-00340-6bd16b95.era1 +510f6645c303a5bef35e3a42bb67561788f45537311938b6994e3ce21d2622f3 mainnet-00341-e0d9d5cb.era1 +3ecdadfdb461bbe51b78adc390fbe1a0a62af515fda9f673fda32efb436227f3 mainnet-00342-203bc599.era1 +3192d942c5fc52cb417fa533bce24cb75b2b3ee7642b0917d68c834aa8bd6df9 mainnet-00343-a668f92e.era1 +f30fa7c0be0490cfeb52a219e34190ea0c4794d63b7ffbf52a9b0e3a78d5cbc9 mainnet-00344-9cfd6013.era1 +75ebd51403dca99b2b4af773e9e38b705d137daea79cb8bbe4aebdc736d081c3 mainnet-00345-54595ee7.era1 +31d39ee38b82e05c35b3f98d973153e905130dc0746fba15e8db5880fce296c7 mainnet-00346-2297e35e.era1 +29d62be96827f03a2e6ce994be348df7b81fb6eea599bdae9e9d8b3322a2ed5b mainnet-00347-db8912b3.era1 +2a09d0ce3566e1ff1e4f1913ab021eacf7edf57244bc22ef9a3d485e02ae2c68 mainnet-00348-1dde5ab9.era1 +7e9d44abc0c85b06c138781dc9694f4b5c902def74f6f6b90d9bca4f902bdce1 mainnet-00349-7e25d7fe.era1 +7b286530125adcc21fbd3d08ad29b27d9005b51048d3be73a17d7606492fce11 mainnet-00350-2bce5715.era1 +d837111205b43025f5d6dc3524203fb901091491b5b1e3c998366b75ac5aa213 mainnet-00351-112b61e1.era1 +d9541f10b1a86c867ee32c39e38a9d7cc74d2865c6f111bcbed5e019dff93092 mainnet-00352-2ffd764d.era1 +49eb0817515d01c1913055ec9280ee5c1998fe5709da7687f9e26aa5c588d95a mainnet-00353-8d5ed81a.era1 +b2323b55726ec90ee2c8eb62fcf4c8a13504f9af80e6c2951b0df13f8b02526e mainnet-00354-78c57cc6.era1 +ee66a1433fb112d363c195f15ac63ac3c5115bfd1a4acdf942198068f0221067 mainnet-00355-55973475.era1 +6f4476ee25d30a33bad20eb1b46a3af49748c858033c14d0a315aca6387bbbc4 mainnet-00356-c7493a6e.era1 +7dcfcf636800c8396a9ebc28227c0b6891ddafe4635989c37a54bcb5b12f25f8 mainnet-00357-e5dd9171.era1 +35148d904c5dfa5d2a40ec89a7f7dc020f4fec1edd685272270a0fe9c4b31864 mainnet-00358-60ed8451.era1 +6c8f45131f9e0b7b0e7d74e9ee836590c484a52d1000e0882a7d83c4f3d2055b mainnet-00359-eeb9573d.era1 +37873b1e0fcb60f7b7de68b84cb08db41b32b61dc64163f39ccf5948ff08efcb mainnet-00360-277ba2fe.era1 +c66cf63b180e2569f2d6c72d780af8c01cb8b7d6948515435e095b2172daefdb mainnet-00361-fc97c47f.era1 +48f612db69c52e246491e750e5f94df47b80dba15592b26b318ed0e613178830 mainnet-00362-77f810e7.era1 +1b2179d93b57c2a17875b444a0c3d1fc4097ff084ba8e6bb937bc092e04d3edc mainnet-00363-056ef66f.era1 +7ac13fcbf596e3e8c23040778198077c0aebfa3f0d03c39a70ecc000218f62f4 mainnet-00364-374faafa.era1 +a4c07f6a1c9f6d8325e59ab32efa67242a7a57045bea8d55eb532493ecee9f8a mainnet-00365-a959566e.era1 +e9388ce5ba91752066804f0686d836887ea7b1103933e291668f70ce8c5de325 mainnet-00366-905c4a52.era1 +b475829a1bc10c1c74748cb87a5c0e2f839bd5e6b69f986ee2d05d6cc2bed562 mainnet-00367-ed4e7dab.era1 +1eddab130d93a1f6d4b87fe5d2bf03f19de10953c1ba49d23b2cd73ae3a5c362 mainnet-00368-b4a84335.era1 +e49f3b85041bc16ddf43279060c2e3c123ab2f441b309dc582f8b5ca3d46e89b mainnet-00369-1f3be833.era1 +a84eff31f8c984e5ffe0b0d0fd3c71f21e3337d8590778f72aed4cd00a337fac mainnet-00370-ccf6672e.era1 +5543f4f45161c97173eb33149431fb42cd60351d3a47cde9d9df3af0c55cff36 mainnet-00371-1aa762ac.era1 +9c4bd2e345c961a78171424a04fa289b2ba87cf9f96c46f388820cd970934dc0 mainnet-00372-05d7f23c.era1 +c469096ccbac56b9d2430d9c701bdefb3f3637bcf007cf769e89320454d04314 mainnet-00373-9a832205.era1 +5aebe7c74581d12fec8d08db79d8691c80b55642bdf2a20aecc68b1f9620dfc2 mainnet-00374-dab73b8e.era1 +61a2bd7564b57b1c09df53f21cc290935f5408fb17e9738b7c50748588b9ce50 mainnet-00375-e97d6f9f.era1 +f93bb38730e0585997daf5e0f200955d19d7ad8e377348bf82e9f33c38c93701 mainnet-00376-6af73957.era1 +086d1ab1ad0bae35f365a752c9b65edfb6de8aaf73f4f44e764c8b8d502eb07d mainnet-00377-fa0bd020.era1 +2fa64acb1e994584a32f066784e8a1372a4bda26c2a9bd666f0c170211e31d39 mainnet-00378-85b101eb.era1 +ee8d899c60918d323b752102b7e27087c3474d95378d1bf57a833717e7ab0c51 mainnet-00379-fbe01c0b.era1 +46cc8266511d62f79cc181e862b0c5c4924e81ff1b33caeb67d3434e20551941 mainnet-00380-3e90265a.era1 +1e98509dfb62e17c5f06fb0388a1eb44a586e7ba636567d2947652e7e5e0e53f mainnet-00381-0b316492.era1 +b973f4831df7a43b82d1006cf2be4826ec3160336b78a9b12ffe5cffff8f8e96 mainnet-00382-a02e585d.era1 +e68d474a4b46edaeb641c973d00bad2814c7e590e7171ed009015c6abebaf914 mainnet-00383-2198573b.era1 +17f9393733c93d004aaf59fcf832c09f013f47ffcae3aa7a81a2e19e923ecb01 mainnet-00384-0c367f63.era1 +2fc3cfcd0f1188247724e5c2e2e7379a7202651c59b919a421cf2928254dba15 mainnet-00385-8893c8da.era1 +c2017d7d6f0e564557eae95368462b2b9bdc4a7319f9377eb3ed17ad97c462f1 mainnet-00386-30637c5e.era1 +a5a18058a5fabc9ee99d16fb2a6e42de640e941233dbfacd19d3702d838c9ff4 mainnet-00387-069b5e28.era1 +5d898b95222612813fa0f52b81c0298a1c37f768cf4dc00a059f155ee8e7e0d0 mainnet-00388-82890633.era1 +c7645b3b2019799b9ff38355724030216fd0a48a398263edcd21ab7c73fbff78 mainnet-00389-def916eb.era1 +79ef309a1a41a7af16ca5a125a446a9628f47c9b4176afb50e3687c1ba2381de mainnet-00390-00f64677.era1 +ca8373c3fbb5e219405ec04cbbffa68879b4ded6dd07544af0532dca5a9e7535 mainnet-00391-60554823.era1 +c4c2d24fb97cd258c8184188a7fe997b9d349c62dfcf912aa389156c4933f64c mainnet-00392-01eb08ec.era1 +48fa1fb93ea20714a26c5fec36c2ee0f15d198c215ce0bda2d2562f62fbd174c mainnet-00393-a5b5b2ed.era1 +8fad6ac037743de46833ea43a6ffd100a00b2cb9f3ad0407d54d0b03b28ed6fb mainnet-00394-c96f2c65.era1 +f8371e073362e9d543b36782ab258cd42eb87e2d6c683155b4e04624d495a088 mainnet-00395-c7c79169.era1 +9402bb75c8892c815493febc8ae569d52b6cd2bfabc75401522534093a436ae6 mainnet-00396-98f01c73.era1 +bc11672da09ff239535c8880d1083d41f982d147b737c143c149af770024bb3e mainnet-00397-ece428f5.era1 +f68cc56919983c2fdec4b8c8854e539abaaad4e9d4f3849cd378e2d41939efb2 mainnet-00398-15d52476.era1 +4088ac92ce31b46020624856191212f6d1b2f0489cc5c99d95fee4f770fece7f mainnet-00399-07f40278.era1 +24ebb117e879bdbe930c41e479cdac2ad4152ecaf2bc788358d53c6d6cfe044c mainnet-00400-837a78da.era1 +2d4314ad1f2ea766461a5bf829ba5bbac2d190847febc7b89a44aa3aa0e70ba7 mainnet-00401-f319bb85.era1 +34d577cae57e3e8fb2000127d0fc9c814248e6ca2af94d9ade2546c85ec311dc mainnet-00402-28918ded.era1 +d1b7d976d494fdd7290e9c4b910350a4ecc850520d072d3bf556b7051387792d mainnet-00403-8d3e10d5.era1 +bf34ec30154f19b6d6af35495519c0596f291c02a35e22f1cdb36dc37636a3b9 mainnet-00404-729d063e.era1 +37ef95e629c825838cd3aff096265ff3101c736a1dfabf789c30f0e8ee4bd955 mainnet-00405-3857def7.era1 +2f83546b46b79fafa526ed628b95b7ded32e5ebcc549e35cbef3454d9ef4d0da mainnet-00406-7be7d5cd.era1 +fb77db101bcde3e613657bef4451b71fd4dc123ea7f8909a5b89a716dc03a082 mainnet-00407-0a5da5b2.era1 +5415aa49b05054b0d5ff111cb47c56aaa56e9390565dd1187338a8d2f08cb9d6 mainnet-00408-4ef48eb4.era1 +2964715cd90a4f9c867a19fedb27e7e0000b7db7f83a452c8e1f43ff93ccd4b1 mainnet-00409-e4148ff7.era1 +5cf7d4cae5e6646d48c546f19a3704615dd40446d6f509a82a33c82894323a09 mainnet-00410-b195d1d0.era1 +54d28a8f851216be0cabea18dae1197194906b1586e767dc73b7388dea6153a7 mainnet-00411-ab2766df.era1 +db229733b6c4cb5f3870f5ddc0d810b73e33af7a75ccdb81d6b8cd3aa988531b mainnet-00412-4fcf3d8c.era1 +ad7e77249977c6d6d642a23dcca97c2f6053505567739a1f3dc01477c94f5a06 mainnet-00413-371970b0.era1 +90f77c70dcb0d58fe7ab36669fa8a5acbf6406c952738352cc84a99f723a59d8 mainnet-00414-7525f2ed.era1 +eb22fc6619ae6d605715d55ea954902aa31cb2f015ef4134af497a39e7cd7804 mainnet-00415-4820498a.era1 +a6fe2ff5ee3e391ab69c97d342aefe88ed2e2146870eab6569dd4516b2677866 mainnet-00416-55dcafa7.era1 +5b99127fbc5f6c24d4eac783462e2379bb7f4fc70909c43e829119e1d498fdb2 mainnet-00417-9a836cea.era1 +cd41a4ee69f5082e38f6307d6f2b94fd51dba629f8f9b41b49e068408a148e55 mainnet-00418-c5248447.era1 +037c937e58c4ce3959641aa241af4ccedf4db7c55e179c73e2da0ac45ba30fdd mainnet-00419-aa00e844.era1 +15d65319cdf5dc1e76c7aaf4e7109b048cdc2e4929d42dc6131259cdcd316c67 mainnet-00420-1a718263.era1 +18505aeee0cb67e5b08106145b4a17efbb9340d896450b789c9581629b1e859c mainnet-00421-b7a77195.era1 +edb813dbdce2343f9b75698a75b743e51c3a8414cd4488a3b78225802e8d8788 mainnet-00422-05e01b82.era1 +c18ae35aba240dbd82651d7387558b06cedb558f47598d0d369b3335174a76cc mainnet-00423-0c5c2035.era1 +547302236112ceaaae8a85ca0176d81dd79193b932174dffd6123267602ce9c1 mainnet-00424-7d31cd1a.era1 +12fb9063597f62079d3b445e4a927414f261875d793f326eb091d310a9d15436 mainnet-00425-737fc200.era1 +281d9c52930f84dcb7d3972d55eed330227c454f00348edfbf34aa505253c5f2 mainnet-00426-b042cd22.era1 +eb20f6e387d6c977608b08d9a3cbed74eed31ddd276b42986df8aecf851f535d mainnet-00427-a5f8fadb.era1 +529b620623c4d04588ef718211c3798085f63affa234d09863ebe201956911be mainnet-00428-2247adf4.era1 +149459f90e22f39ecd0b3747e0cccabfc1a7ff60ff3d3765a8a6e88d3ed3f95f mainnet-00429-1cae28d5.era1 +3a5a78a76eabf340bd230c91eeb74ca2188bb5a9a893c8c3c25d1958bf07c1bf mainnet-00430-ab59cee6.era1 +a0f6b0c0ee9e935cb32fe509023b99b74a914ed6b740929c766845bcdcea109d mainnet-00431-ed24090f.era1 +610414b9f4d5c298c54a145519e2d98f88f2ca17514430c1f30471e5d880db50 mainnet-00432-ecfb2f47.era1 +3ad76fa4ae6a1ed8d510673ce7d2875b6f956ff0c8cc1af3c4af647880f7a07e mainnet-00433-ea10cb3f.era1 +4fe2fd1182a72ae4e73f9b80480e02319d0a9e10e1ce939080fe3cb367ef907a mainnet-00434-ed8823c8.era1 +637b8cac56d8d9d2c13d1201cccecb24504ede7381ac3b8bab3500a8b7b3ef12 mainnet-00435-1acee0de.era1 +a6d101e7ae0f2f0ee20e7c5991acee4baa08a2480e0b6b61514868562cf2040b mainnet-00436-c3510bf4.era1 +5758607436d4abec5629c29e4de09018668c6f4e3372ade527d220e604c272aa mainnet-00437-f2dcc620.era1 +98a4c4a1624eeada42e5ab55e37de3c9303e692f2b29261637be5c23153245bd mainnet-00438-00f5e21d.era1 +18c0623aa3283174932fcedccb6be4a29ad6735cd2527091a7f5bd4a97240128 mainnet-00439-5149508d.era1 +7c3a144dda6e614f7897166a93374b12ecabf08eb001b5c91455c058c3d5c1bd mainnet-00440-9feb9189.era1 +5c8be22c7adf0f45b608fbd84f86a21289696d14b55988ba997fb11bd174f3e1 mainnet-00441-3f1832ca.era1 +e9c5db7bb9d23f65b7cc7189f2f562e910ecf45714ba134d5078e835d44c481f mainnet-00442-1d30de4a.era1 +a328f5ed715bb41631f1db499dd3cf5d5810492e65878e1313830209203cf3cc mainnet-00443-ea71b6f9.era1 +964f815a7fc2152daf9918cdfdc24742b564ed5a7c9053c7d57b2f55dbf756aa mainnet-00444-c56da958.era1 +b281e2c5e56f1eafa14af3e8b1c648512f15050d8aedb7d76a2ec04ff2e15f50 mainnet-00445-02cff3d7.era1 +8d1ac05b1efedef5c382bb6de1bf6bdbc8e1e048280e03c4ec177450d8665aa3 mainnet-00446-2280f1cf.era1 +4317a705b8a6ad0111850b6185c22cb3785fe58841cf13607bef0c208c0333b1 mainnet-00447-3cff32e3.era1 +5c691ceb14e8cb47a482a5420cabe8a7ec859136a989f47edd12cc451f3faeb9 mainnet-00448-7dd2c4f1.era1 +0abe1d8b735750b2004a10b0a1e6927afe8665a13539697982f2e8c21b6c0cfe mainnet-00449-6d1d274b.era1 +5bcdce9f1193f5da2c6e4be6263139486e95a35f0cf3ffce6d44afddf2726331 mainnet-00450-2b5e1149.era1 +a1a501000dc22c9b8ae03b9f7e4a93222393e170a7ae2827eb97224bc18cf76d mainnet-00451-4abe0e07.era1 +c9fba4cf9aa72ea9f74d9bdd08c694b807aeb480ffbadf04f939992fb2a3cea9 mainnet-00452-42606107.era1 +d2aa4df81dab672f50d3f79c98fec32ee7fcaa54cc1041be58a1834d37f347ea mainnet-00453-23cdebe0.era1 +231aaf7ca5c7ce0107aa1e8520273c18a82224b81f5daa2c98e58ebe5217b846 mainnet-00454-b2b5e5f9.era1 +eca2fb672e6c4fd0e90abb107e535a7bff18ce5c66cb8fce13b6f7dc3cdef58d mainnet-00455-54943c8b.era1 +f2030b4728d9dbb95e6c4a1796ef569c4a7fbbbedefa186f13bd13de303ca0a4 mainnet-00456-cab07908.era1 +a53b67150bd02d6ed966b436fc40e15a76c1185ffece264ccdbdbb068f264e2b mainnet-00457-82d06ed1.era1 +a32713a0a07a3c376d9507c1bff380a082096693dd38deebcb87ec71540124f2 mainnet-00458-2bff3cd7.era1 +451fda4aa67cde3221f2deb7f94e28562ea1d388d488bb77f925b645d8f474c6 mainnet-00459-29e03017.era1 +263844132e6617fbfe71c5aeb5de309aa811aaa8db3022cdd01963719a34dd01 mainnet-00460-6f2ddb12.era1 +5cea732f6df87faa2fcfa2e5abab525acc144d1135fca90c04777159b6a102b8 mainnet-00461-86535bae.era1 +ed2a2f0d305dcef66490a1258e1918f49b99e26ad74352bcdb54b41f38c8a011 mainnet-00462-3658342e.era1 +56ca521c6c281c5175ea66527e0fdc7280f4319c7d4afe9aafb0d4b36e9eec75 mainnet-00463-4f586d74.era1 +c3eb5333f6c002989114af2bd844c0e8e28e6f6e4407fea00e548138f577d720 mainnet-00464-2da57d6c.era1 +7f4c5ed20fbc6656ae5a8310037f16f15e9ca3d4d62d98cf7655c27c5d2240d3 mainnet-00465-afdd52d6.era1 +cca9cf85c9152b6c4eb1d0795ab121c4961553ad6e6613722be52a1a94c4a91d mainnet-00466-21cf05fb.era1 +bc875cadf0d713ccda036f1e2656be47d9f244a715e95990201bf6b47f4d92cd mainnet-00467-27685b9d.era1 +a903dfb595e8ea9d49ffb0e5b120f9cfebdc43b66ab797d406244f40aa61467f mainnet-00468-610466b6.era1 +28b570e840b71cf51b2cfe868a3cb1f0ed9588e0df5f4de7e2e6a5f8182170c2 mainnet-00469-8c5751e2.era1 +f655e24d6972690175ea4dc133e9d5e9b3f7837f3e17d2befbc7b9ba9c35dcea mainnet-00470-2e445b03.era1 +fb4c985a4bb83e274daa136dac66ffddbed69b6189b4ac219d40819e6625be74 mainnet-00471-7f375623.era1 +9df7017dc925a606786d780e02df664b12999b6dce1844a4a2dd2e59e9ff9a42 mainnet-00472-5f279db6.era1 +164d29232a4ef13a37b85d5149f6088b4472f2f43bc46b9e12ef6e9e02a8ed33 mainnet-00473-5ae48eae.era1 +414314c0e27330485dbcd2c689d3db8adf740672bef0cc19083cf3bba54905d3 mainnet-00474-8b70d9c8.era1 +68d098339c7a7d1dd941a6488fec8e969a08d6cea26b93c0cfb82fc1662f1d4e mainnet-00475-a8e53747.era1 +b1795e08edd0ec1a200504de3cb6d02c7dd796ac3c2a3836e7179724c06ea38f mainnet-00476-dd34a7c1.era1 +ded59ffaeabb0ee900fdee509f91296869fbdf48f534618cca664da1860769cc mainnet-00477-488d852f.era1 +982b4a076083a00ea755ecaa2e8e83772b451dad624d58a2abd65236fd7880bd mainnet-00478-232a4fc9.era1 +7cd6e8a704e5871f17fb1d5f3fe5988f90a6fb85b5930066239769d66aee0649 mainnet-00479-4b082f24.era1 +f5455ff560d2ad13510f307730c86674246a48a9417315c6afa02007a7b6ab6f mainnet-00480-b54b802e.era1 +0495187bc1dd5002de2c0eea40b7e8afa409881794ea806620638ae14a15aae4 mainnet-00481-213ae81b.era1 +14f00d8d7612f3dd621378a5733a5b1381a50aa8feb7f5f37e2451b57b1a78c6 mainnet-00482-5d09d6ee.era1 +9cf6cf9a7502fb5cb39c17261fddd3c9c75ed137d165df63e59e8d4e64e4e7bb mainnet-00483-f3c11c6e.era1 +12177883a5f8ad1203ebcea311e22fc6152f42162b14de0e1580c9c2a35b8d62 mainnet-00484-cdc41b84.era1 +3b402d38b246d3ce16eb13767165ee833d32d16f40f74585fedbbeb47f5d2e41 mainnet-00485-b26f2e53.era1 +2f9849026ef56ac144cf56e61b1ed5ece5ba0b513a66175fd7c16e364bf46802 mainnet-00486-82b8c438.era1 +513ff1109a8567db088e57f1eed1236b0bafa122539fe14f85ba2a3f70a08376 mainnet-00487-d834f157.era1 +51993f2f055177c99910a8cfd0af62a09e195d12aedadc8994f9b4b5e4c8acf1 mainnet-00488-fa3989a5.era1 +588a68e84b5483f3903528f998b4e294e0542eb025fea3d91716879156d60259 mainnet-00489-4db390c5.era1 +20a241cdb9315952d266f45aed67141fc5b0eed9610f609a563aed184bc450cf mainnet-00490-b9ad2e4d.era1 +3745f7942b2c1e0c254fe9eb051d59983e9ecdf74cf17c5acd11a1e35391965e mainnet-00491-6aa98f9f.era1 +5708622aac0ea34edc5ea2c6c40d323eb838101def39febbca203cabb7de3444 mainnet-00492-ebdcd70d.era1 +49beb4efcc4f515ce1c5f497114bf1c166d65c16d5b9c47ff2523934a86ada05 mainnet-00493-3079f625.era1 +87c21e393d2396c3a6d42ef7b1dc139b0c95b69c52edcc0c17d4a7aea83a9694 mainnet-00494-33f97b59.era1 +b64261ac3156a8cc499da652dfd909338399a957cbc8bdd2f0c8b792ed61357c mainnet-00495-ee3904ae.era1 +1dc0fdd218d106d7559d046e77b30992ca0926cd7307b95e4f8d0bfd3534ad17 mainnet-00496-cdf13c18.era1 +49801e34f60ed5986c876b6cc4ec010423a25e029eacc8c9b903dde8e6c58da7 mainnet-00497-27f7ad95.era1 +86b7545b74e9b6ff8d4f2272d2307c725043074d362c8ec669ddecfdb8e7f2fd mainnet-00498-fed48beb.era1 +44b03694c9c02c3038d22b134c2ec1caeb2c8802e9b350e76b1ffbb7e1806f24 mainnet-00499-d9c9a733.era1 +19af4c2cba365b97f2e8e04dbac106c8ae4880d434aefa7f373d143bc1e6fcfb mainnet-00500-b11653db.era1 +83be8e12e664ac4c6cb455f832c36a8537093a4b94ea9d4c45e96ac444f5a522 mainnet-00501-b202cc73.era1 +580ef812ed778ff77930be56d0a3b15ed6e1610aa9877a2a4656fd0e82819644 mainnet-00502-19ef7cc0.era1 +a52cf41b1d14b02ec3b1c70a8904a416370a15a1f014d1e63b5ee53d59ea1e8d mainnet-00503-45f20620.era1 +9655fa5d25014d2d47e21c6006cbd66ab29bfd3022edd282ac745e27a7161717 mainnet-00504-21e3a8f2.era1 +15385a304034611f7665e75df8c7efdef6b39de3af271cbbb23fb23ee9882695 mainnet-00505-6dd1ba56.era1 +f4feb4ae45164687d99f194a2377359f90a53c92dc5fdec01e386b6d82ab85f5 mainnet-00506-c0414076.era1 +b7108796a98dbca3865eb23d040f2f2bb7b81e5613363601b05e38007599d5d1 mainnet-00507-a7340f2e.era1 +3835eb369cf4a7c1d7f422a3533026d4c7f39e824c8db0fc5b06decc76f35f93 mainnet-00508-dde4c38d.era1 +58328611f7492611aba568c1b1bf881f0c4712047cda5e474dacc20a6f54b800 mainnet-00509-fa5dc42a.era1 +de13c1e15738b569e0f2e39d2ec188182dd1b607e3dd62806b98ed29f36e83d5 mainnet-00510-ea2b8d47.era1 +1f0af6eaf3908eac69ac0c7daacb17d012f8410cf500e178232af0d9b17d699e mainnet-00511-d5d2416f.era1 +85497cab605da0915dcd15f81784b6dea663f5823162ffe17ba9e51d5219ac64 mainnet-00512-e2918e50.era1 +f815f4014da4b936f60b4a597c4c73f381272b465a0c8ddb954cd20018983edb mainnet-00513-d39eefad.era1 +029afaabac6f5aa8249f971cefd3843166239f9cf087cda5b8ab7ee78774cea0 mainnet-00514-8bd8f6bd.era1 +9ecfaf77c345db1c7194277b1b7b52a3f7368df97003d7161f23554e39a962d8 mainnet-00515-66d4642e.era1 +01cd75539ae70d3ce141f22490a225c602f705df3a7e57db12428ff68768d342 mainnet-00516-ed3b1187.era1 +68ebb5b3d0d41e8c255d16a0a100b41272b74ac23a40c3f61c4ff30a4d53d2b4 mainnet-00517-5ef487b2.era1 +d5d7f46100a8ac2ccc7312c7f56e951555c14bcd9aef4faf4540c2fac3005487 mainnet-00518-71027029.era1 +773e464730bc33535b0795c24c47eae3f75dad5661f7cb9e3a723fa7737d2afa mainnet-00519-218c3b62.era1 +73c2ec4fd8b5ab8fd994866d5ea905e02f589f0bfd17c62b60586b5e90faaa3e mainnet-00520-062e1719.era1 +c4b190b473cbeedbf892d2d3c081360df71b038997e0466820fbf39796fb2f13 mainnet-00521-5b55367f.era1 +433aea03dfe9a761ea95d8fb326d545596a6b6ae24af3bee9b9c7e5abae43367 mainnet-00522-dbca1ed3.era1 +3c279449419da666df1e2c8edc9adbfa3f6c2481921b0f0541e03e19db77dccb mainnet-00523-297cf9d5.era1 +3a1a62e5fc02eca3e2061ca7ec0ed5561dfa031bdb104cde4419d6841ee59e43 mainnet-00524-f389f3b6.era1 +1cd54284de4fbbcd0b9d60eeb837b50f91f92b167034e4c44941ec5a6556cd1b mainnet-00525-d851e822.era1 +bf17ca4be7cb2c307fb5f13f295a20b448d819928ea5c588072f6da9ff2e3400 mainnet-00526-c69972a1.era1 +05e4db40af70a7e78ee362faaf381b877a7add46e3ce1f51ae7bbf1e9fa26ea0 mainnet-00527-2c103256.era1 +3a6ee2131b8b4283d1a30f2b1137106c461d0c26e3d018c8dab506b06d87daaa mainnet-00528-32a674ae.era1 +ce09d7816ef22ce8e0431f1a482febbba259a4e28fe7cfc486441bb41d70446c mainnet-00529-1bf711d1.era1 +7e9d28e51f686b6a1012942281ab8bc0b410784d2bed7f7c987a35bcaeebd904 mainnet-00530-aab9d4e3.era1 +26104ebb607588e04ce2323c4b3891f9cab06244fefb505609acc622cc40f749 mainnet-00531-0f51dbca.era1 +120499bd51f65e76117aca0674c8cff513589f3274ef70b183d170ca4f806728 mainnet-00532-b4c6703d.era1 +eaee56370a0bdb1309d4c2ff52fe804e7d2164b5469c8b72c4957ce8171586a7 mainnet-00533-bb2932ed.era1 +2e6cd452bc720c247941118e8a0047a3c7ebe561b87bc975bf87b195d7a64bd9 mainnet-00534-c65d109d.era1 +f0a6b2bfff8e75bc5e804bcf9c0363ffd19ef9e8ee45cc132fae638b77e23bd3 mainnet-00535-bb367122.era1 +30cdaf9922f008643dbcde8528730c0dc30799d34a43e2df58eaa53210e2434e mainnet-00536-faadd066.era1 +f874f4faeca9a98e5601a53898d2102617e9c0c57738ff691766c78139611c8e mainnet-00537-576b374c.era1 +f0783e7c936d1b71d19bb4abe24e8a1e7e70f06b65d2ec7f7e8a00bdf0d0f1ac mainnet-00538-d8eab6c1.era1 +7e5262ba5514aaf42edd137db7587cde57279d90b43eba05b9b4cb6a866989f2 mainnet-00539-2c32d06d.era1 +058a5cb9e04e96861a4821b42d087c6f876dcb65119f8e40df0d79e06018a013 mainnet-00540-f3078a9b.era1 +21636685ef41978eb7a796969d98ff8c4582021b47f204b2e21f93652f1f410f mainnet-00541-3063ad60.era1 +501ddb0a72f282a9c0c04252eb7aff752b3b7d1336f832713a11a0fb17bce918 mainnet-00542-90a242f8.era1 +121e55143583932220273c895e9eedce10620c044f0f5431550cdf5571d9928d mainnet-00543-be9dd353.era1 +f3e298a94342fea1557770766082e47347e48a1b219e91791534e56dd7d88a26 mainnet-00544-1c5c7615.era1 +4285a6021c374cc02e0b7317e1a069e8a3ec1dde760b901a7c542e92d97e7636 mainnet-00545-e6369239.era1 +1d7616d952fb561b06d1fa898c8c3849cd66351755bf56d7d3ebf2cbc4f7f058 mainnet-00546-21351413.era1 +91a8417bbde8372258e4ea7403e9e711d0df6fd722be8b2e73494b0359eb90e1 mainnet-00547-0fd9e031.era1 +84cd049065fe0f7f39f23d3c96d81f59a54a94170ef4632429326082a8ca3a6d mainnet-00548-e318be79.era1 +4d5332a037b993314883f3e274e139314a7b8d2c916cedaaf535cf7ca04e0b70 mainnet-00549-2dde72e5.era1 +73dd18877d5cb50629c1043ac51fe95b9cff600494a4cedbf5aafc45a09b5abd mainnet-00550-d89b717d.era1 +8cacc8487d8342e2aa6c4642b0e14585797448d0a29a377d00719f768bf17cb4 mainnet-00551-a8dfd860.era1 +1ea0ddf1d4a156cc3c5d055fe0e90516669f80b29265222815d54bcbb1257d7b mainnet-00552-d6a3521a.era1 +afb3063c25115627793da7620d1f118548789a2d34d8efb175d8aa51aafcea70 mainnet-00553-f702584d.era1 +746d867c504c5b0cbe642f9566dfb007fb4a3184fed3811a49c38b05dfe34006 mainnet-00554-700d58da.era1 +1186a9337ad0b4c9c2335817e5e1f6b7359093ad3da2a40cd108d1e6537c856f mainnet-00555-41db6d14.era1 +63aef838d5c3f9acff8e3b678dd9248b6e2464d6e5085cba0a2dbe37a5623922 mainnet-00556-3503dd53.era1 +6b779cede943e8d4cd55da81fb9ae43faed525d0bc25e9bd2f2b94ca6d478121 mainnet-00557-02391085.era1 +9ce299b548477737341d6591775f8967ae4f09b5bf1f23baf8c477838eb9c364 mainnet-00558-ed670fa9.era1 +e7cba63e763a2fa24ab9d76c54104d1f2deb017ee5083595c10278e7281e0c45 mainnet-00559-63277435.era1 +3361e01e4e11b8ea2f6867edefa813195b9e3c67ee01d0883788932b85285c09 mainnet-00560-e89160d7.era1 +3fb208b1a30c3cb39954a8f7403c4ffaa5d4bcdfa967ae6d0d83d807a885831f mainnet-00561-f95c755f.era1 +076eec9208a1a7c1f2f3575c2eb52cfcc98ceef632aef8cea724c1be4e1fabeb mainnet-00562-97a6fdba.era1 +864299fa4f4daf4d0c48230f831a70592fd2b854ebf0b7bafeb1a1b5634df17c mainnet-00563-8aa6ac0e.era1 +2c32656b7c27705a4807c827bc3545d11f2fbcf7146c29518937fb89f3ef8968 mainnet-00564-ba8486b8.era1 +7c7fd609e45de5491e46be7ea7ccd097b208fc2c88e16980c4426dd7205a8031 mainnet-00565-7cba894e.era1 +2f42a73fa8eaf0c1c0dc53f8727c5fa579ea4d4b4eb838bfe9cc61d7c0f92fea mainnet-00566-54b3e34b.era1 +e15a38d740ab95ddab6d31f2a4d1419ec17a463a2e6e77fca9efdd78c29c260d mainnet-00567-40280a85.era1 +0da2dc7c686f59ef96b2db151f763480d3a881645c8bf431f4dcdb996d0818b1 mainnet-00568-ad863b1e.era1 +de95cf0a8e2d4ba416296a179d17e1c3206e2fc537075460193979f67cf888b2 mainnet-00569-dcb283ea.era1 +3fa3cedaab307b161d1a8a6317ba34f15a1239e3cc30749192004d7daa1653b6 mainnet-00570-fb912362.era1 +ff4d8628fb67ca2337f55f92f9d1c23602e5e4db51d6df8e209e8900087a9263 mainnet-00571-b65f3342.era1 +1ad917e8e7a61f0833399945c9e687a65e7802309edd9ecb37421d3e8d1bdc4a mainnet-00572-dc59179d.era1 +24471e846f24c62c93f126d7501cae75867f791a8129dd97a8a1a7680635e386 mainnet-00573-21aec308.era1 +d9b8550a87770cc0afdba48e976d6e122ea136a7071177c6e4f13fd393e794c3 mainnet-00574-55e72fc9.era1 +f04623ddb0eb35b6be08f15e0e8b44ffaab1d8c3da87f7bd30bf1355f4471752 mainnet-00575-f6564eb5.era1 +f651f045ea114e31eb027b82d7531167fe65c4004286ee8555e8f03c4f8ef161 mainnet-00576-923096d4.era1 +fd857476eeb1af8743993fbd0608cae7aa1c14c757db07e4c9198378a77d13e2 mainnet-00577-5914605d.era1 +b061083da7a861c1bf7d58da0913ce7e28d09412d0b10e43e1ef600607066a2d mainnet-00578-57d591a8.era1 +06e5104850d19d3369d8499ccc590b98374f563d2ea77a10c6292cfecd20f4c0 mainnet-00579-705b8e04.era1 +4ee6f9ce5e5cda1381faebefb06c6696cb02ab2c6cc9a8c1692b398f0c4f0f36 mainnet-00580-5b210184.era1 +aa6ea1063f36beae91cb1dc14f1e758c945e1b1435837c4c974fa183ecd5b766 mainnet-00581-d3dc3f99.era1 +f0da6705ad1a4ec97a2e877ef9e4faa3f7592d04fd06e813bbad77c55f670b7b mainnet-00582-d6b2c7ef.era1 +d15b9640646d0a3f7ca5c96ff12f2439b0a0b25488c8e82eb381adb7b1e21925 mainnet-00583-43400160.era1 +6a111a0d8631dc36365127b5b86267c413fd7a6836e56d5eca1026495f4bd143 mainnet-00584-21b2682b.era1 +4f5ce93c8872a6ee42dcea100b0543d6f37c4af82a7a87ca7b0cb289c8a7cfd1 mainnet-00585-02f0b151.era1 +d3ebdaeca270a0fd7ce27195d6f227993de02e775b11d7ff3ade7d6ec3ac8032 mainnet-00586-60d868cb.era1 +ecad45bc22fa043a181d656b0270ac4f45c232f2eac5a54fa12242db64bfb0eb mainnet-00587-59cc91f7.era1 +4a6a589355b5cc0fdfea3adf27751370f32a9a1c911ce760d83c587c20f25207 mainnet-00588-efefa87c.era1 +9463605b6b5f6cf4c7b0a888d9e43409f6e97f7733165349fb01773fee6ddb5e mainnet-00589-85c8dc20.era1 +0f1526ef098bd10ff59ea57c283dbfd2195824748b83d80c6fda5686b7c76851 mainnet-00590-2bd79cac.era1 +146f1df8637311b2f1fbf58cfdc3e8c6d3c82e9064ddf55cd7623f2f27dda77c mainnet-00591-d9b21bd9.era1 +c92cf6a221783f9acd08c79e6130f4362ab25b871127705d9424b7bea0246020 mainnet-00592-9dd2dc6a.era1 +847870a9fb4096ea2dd1f297a2151187d68100cb6f07f777e3220ba40b41ffa9 mainnet-00593-0a9de411.era1 +6f31046df50e4ebceac9e592b488ac7bfd49952661cfd3664888b5c0760da0f1 mainnet-00594-54bb5026.era1 +c3dd517701c421643251fc581192ef1b111b1ecf45c0fa3dc568f53488c94bf8 mainnet-00595-08fa2659.era1 +38d4e79e4e3524b054563e35b497aee9931b88ed0aa642114ec8a0cb385c30bb mainnet-00596-5e2423f9.era1 +b0b62ee0c0830fbb9aaf7f500cf2d7d636532aaa4200fa7ac5095a681454712d mainnet-00597-49b11d14.era1 +491ec13b3ef1ad873607254933d7f894f9257cfde114ea633074acc71f67f675 mainnet-00598-050d0b97.era1 +b705e64cb2580dbe83c38e4220cd1a0420b29a99e94d888c3436d6dfe8763211 mainnet-00599-a19b1a20.era1 +5867f93ea1a0462fcfed3038757464c0c932a713c1ab9ef5c5639aeba80f3da9 mainnet-00600-a81ae85f.era1 +eb9f78165da14363c498cb339eddbb2c6766c00b4c033f7b99bd593670ef7b72 mainnet-00601-9e26205a.era1 +3c95474d17a48074ed8545c42927f086b6adb1d59d0fb6bedaf189309c9608be mainnet-00602-28713614.era1 +61b4b1139697c6282a6328a9d146307e98c52c2c7db51723e7046d3fb0588713 mainnet-00603-9a115bef.era1 +05a250272371db23f2c5a391d11bc2856b803855121163e326d2de556644149e mainnet-00604-ba62e002.era1 +033a4bf1b53f3d04f903df7cbcdb883a0eb407c65fbd274e554858909f0feec8 mainnet-00605-0d936f16.era1 +9a5db5eab59797b36203aa0276246d973e663d45850c9f0c2b56d1cb6bbad1b3 mainnet-00606-ae859b84.era1 +1a5d3e0a9cccc60d553a6ba1646f18a07c280e918159e72654ecd347277d42c1 mainnet-00607-62d75fce.era1 +1977fd6f4e3fe0c278c8ca04e46b79314ec07d02e885827ff5d72e3891556187 mainnet-00608-d449c48d.era1 +266f2d868f41878223d57b167b555447610fdcaea375bd1c40bbcac087c10470 mainnet-00609-7e60445e.era1 +0cd85b03694239516f90edd8a59d6ec9385aadbfd28d2ba3cb49a21a0aaaaaf2 mainnet-00610-2f230cba.era1 +b128c7ac9d8f20541803ccce5cfa6b7a49804b1d115ccc0b44ca023a6749aa4c mainnet-00611-290b8c2b.era1 +958cddccb94723db4013a8e54259897fa91df9c3c56d0dcbbba3e753b2e73290 mainnet-00612-b363f647.era1 +b0f6977d0c4dc7b8c288a5dbdc30b314443c6b2ca1aa6de9cd065097dec96c41 mainnet-00613-80a4144c.era1 +6eacd8cc703e153abd9d63b128c4f442fd90935b5f6344169755252369a79b2d mainnet-00614-20913bde.era1 +027d09aa99250322cae4c2f6a4033252d3b787dc7cfebc6f51077b554ce3ae76 mainnet-00615-8b6e7a1e.era1 +e8e5a7f53abb982b9f658cfe7def2aba43caee175d5e053ea748656fc6a330aa mainnet-00616-bd35481a.era1 +e661d9a123138573e618f8251c46675c9094a76c3533852c5d54206c74a47d15 mainnet-00617-624ad401.era1 +3e10672b6ffb5a6bcc59420b2d5c155a87066b033883f9b8e668942298439d5e mainnet-00618-c70c6f7e.era1 +dabd9d6332a1c1f429e5b581fc73ab595d6c667ecc4598c4f1c250ebff4c1c27 mainnet-00619-1b807ced.era1 +0c9d1874174ea831bdbf74616811eae0794a0c881e8b08078dd6851733de7773 mainnet-00620-85065023.era1 +17e8e3a04b8bd7bd414b5bc25c4c9f66ae524337a4354a612f49bb4f74734945 mainnet-00621-385fbb21.era1 +d99a5e65a0f80a12fdb3b0b3c745ddec6e5312c3364ef46485c06d9748af97ad mainnet-00622-92fb5e57.era1 +3026bd1407e02493df937cf5d57e67421b94284780874ab475962071712a4bdb mainnet-00623-642081dd.era1 +31e47742ac21fcb1b121c86130c4f044aacc13abb7df3c67dac7a442a1adb3c2 mainnet-00624-1d72d627.era1 +941fe056f09b29ff179be410567e07fcee1ca191d0599ceaf869c336891d5174 mainnet-00625-f7ca7cb8.era1 +d31fe29f030c01f7e49ae70472def2ecb1872608a23549ccfe521c02b4b282ae mainnet-00626-4f92dd26.era1 +9574994c5d43c9b2aef288b599c29a52ae4f942bfb6d05e5b75b351fc84f2798 mainnet-00627-06e70723.era1 +c8815a923482ecbc634ee658595e5333bcca9c53aba119d288090c4437013b8a mainnet-00628-313cbe43.era1 +5f7da2352308eb1274e73800cddd672f8ffeb1cfddd3574d780dc31b1d5e69f8 mainnet-00629-e939c151.era1 +207244939f8f19921eff5064ca9f109debe695a697464dc5c7779b587c60f8be mainnet-00630-1fbd3e9a.era1 +80128ec9240a841bae7d883ca736a923014907b5529c71ccca0204285b4cb7f7 mainnet-00631-333c0583.era1 +8c558409dd45ebf8633fe459a03180f3a141ef56ee355e99ab615c6ab6feeed1 mainnet-00632-bd6027f3.era1 +88db31cb6128b4de50ebc719bf28ef010a103214427e5c37e568cd42a493d946 mainnet-00633-2fc5d74d.era1 +32c8e4076799588f1cd35559ef2830058d7f776da6874231b83b46eaab84282e mainnet-00634-5b3c9d59.era1 +72fbcafc97d51ef4cd15dc5a2cb7a954cfe497554f1486ba69d9748a2ca21ea8 mainnet-00635-95e4dede.era1 +932eb65ac3753538380a3b2f1ae3be2a56fb93db259771c3ba24c7fe5d978de9 mainnet-00636-f8124b1e.era1 +5adbe1f6170a9cc09f96267601bc4076e350ad36760e207c69ada235c157a09a mainnet-00637-12daf758.era1 +599e56da4c0cfe52eac27a988679cec886cbc64038bc1a9f3989c61e660f758a mainnet-00638-75957ec2.era1 +6cac0942b944eba26ef6f87fd9529f35bd340127744ec1fe58414e823ce548ae mainnet-00639-7c4f218a.era1 +de762fc2f9932b012470f51da960775a5323924b62e9055a05ec6792a16647bd mainnet-00640-3cdc6132.era1 +afb93a2efb314c5df655789296901dbc0ef0411534d44d0b22ac355118f546c6 mainnet-00641-471f9e80.era1 +349f4285db586f9cd6e3b0e86ca25e0b500e9802c9523405c453e8753850f92a mainnet-00642-551764bd.era1 +1e8cd0ea9699d6bd1a3cf0a4a41f6f20857c72f78d5774c3e0835fb96e8c2820 mainnet-00643-368d4f6f.era1 +de6b4dfbca85c05979a61d538283bfd63068471487561a826bd6549208e36b89 mainnet-00644-81a7c3da.era1 +afc34e2bcbc18f2b3baf86aad08cb934b08322168564f3a57db8cfaee4bfc0b3 mainnet-00645-2582b644.era1 +7e58250e2a5bbd7e4737dbd0f028fa972519d6a4c16474b7a2987ba93f6c6f79 mainnet-00646-7fd3548a.era1 +de98a8249f13257740e2a39381933eb4f0050452889037c6ca4219e874ef7193 mainnet-00647-07e93c81.era1 +cabee428d74add0d820ce6fcf617f36dde5408a25c627d15c1c76a64b57dc94d mainnet-00648-01a981a6.era1 +257deed1d444ca8c838fb953c08846dbe6ea5de22b5d26ae9ea243c6a8c3f0ef mainnet-00649-05bf160d.era1 +57eb9ff0d06f758af8739d12aed01a8d750d5f19ff18fb41355f78a6da428703 mainnet-00650-119bef0c.era1 +cd625575d5f2a3b546b1801cb31de9854d592790d50527bd43a433525335005b mainnet-00651-4d3f0b82.era1 +87202ccda9b11225a8d097e495b1f62681206cce56e81600f22e4057858361b8 mainnet-00652-730975c7.era1 +3a1052f205840ca993bbc3225667b593aa5479f7d80cc3b27bfba4b07fa8de07 mainnet-00653-2eb89f05.era1 +95ab2a49aa68595de236f97733f6b99c22a8b7fe43f512e3ecdd896f2d84b9c7 mainnet-00654-51b0bde3.era1 +8d4c7eb3aaee1522398a5e232ef4febf4027f3c236502885faa891e9a00ebbf3 mainnet-00655-06381406.era1 +aa49d7868cb14727d5bbed6e8d48290af874c9feec7abc6524c967fd649fddcf mainnet-00656-0c072423.era1 +f52ebbc585811c9c26d15986ec927122c88eb1b840746a3ebc831cee403bf02a mainnet-00657-4b0dfe65.era1 +4d28f6ff21fb6fc3448d7bbf0cd7e7c92a2df8a339df0259400b4cdde6f3ffa1 mainnet-00658-eafc91b6.era1 +3fe97ada56a3ecd29920cc28f088817fc384e4de1028991566f4ca46b7cb9fb0 mainnet-00659-49e7399f.era1 +12abdfae11202056ebe3a89d1fbe165aef5ed2b4bb83608e249674f5323eb211 mainnet-00660-376add4f.era1 +2157bf342557f8400a1dd5fe4ba08105d8e97788469c25a69fa7df9d1bb147a5 mainnet-00661-a8a70e6e.era1 +4cceef1dfd6ca6fcf875461813ca98582b5cc6bc3fdb178c8003f6b88776e637 mainnet-00662-dffecb3c.era1 +defe253696a6266c6fab5c8ebc6f5539bab56bbbca80e6897b603704c20d5da7 mainnet-00663-6c4ef261.era1 +e292d90ffad574c26f88140a0fb3adeb6e0feeb42926fb2185ec13ded5dde951 mainnet-00664-3eb2993d.era1 +f6d998485da74f49e00218f4fdb9783c3a7d51192958c020a6f49aaf2edc6dc4 mainnet-00665-8f406786.era1 +e582415262cbc5638f27219f51c9540fcf6cb8e30ab8d629f205f965c58bfdc7 mainnet-00666-4ed7ee7f.era1 +327cb6bb9586ef1cd5776c856e0b838044fcb12beaa4b986066585f9b20a1ff5 mainnet-00667-a6b898d4.era1 +1cad75fb6ad6e754db1b3853171fd4eddd48479b92769162a0602014b090c094 mainnet-00668-c4a9d166.era1 +e22ac2e3c703357e2c18b04b19ea413697538ffc1acf84d87c386d1d9af08836 mainnet-00669-d8d97842.era1 +372ad46d1309e2c31bca31da93d1993bdd42b3ec5cfb16cea5a4cb7e3253658e mainnet-00670-be3afc5c.era1 +2c2682a6baa86d8bd465e124cc488c94b0d151d6fe942fcf6e8bf073ac445cec mainnet-00671-bf138a26.era1 +43124aaaa3f46a7505a988731de60b0f095c3a119184ec8463b93a13d8f8fb8f mainnet-00672-bf106779.era1 +38b7dd5161b825fcf13b8c84e6f885576dc748e73cb9cc3417419ff738591bc8 mainnet-00673-defe7756.era1 +a48ded2af1b573fe6574124093f7f070bc374ee339e9b68a2f512455e26fc77c mainnet-00674-c6dc6388.era1 +4491cf363abfbb3c9f7c4c58013facc62788946fd9bf36b0717d28d03d5b8798 mainnet-00675-1e729aa1.era1 +c4c629a38e80616f50c9c79457ffb31169e1db56798c9aa6467ef47db2be6698 mainnet-00676-a5855d98.era1 +aed81eb7e8722c02febe53bc640645d76a03176a96ca2716828504c0b35c20cc mainnet-00677-f3e17cb0.era1 +b7193ec008a5f6ad77cb2d38e25382491e519652068c2bd8b8424a99ff672eed mainnet-00678-42e73724.era1 +9703fd0c87a1b44fb78073d64f25b680bbb1231436be09153898a1562ce54a0f mainnet-00679-f0fc97a5.era1 +df514a67472e6534e222756e1fa51f300e90b1a939b33401df6e72d5056612b0 mainnet-00680-a6045d36.era1 +c09ca9581d1b07bc6e6a2fb949dd21ff1d985c35c4e453cbaf4e108209cfb117 mainnet-00681-247222f0.era1 +5e7b3b9e90efc074faafa91a1d9a2d59f5260bb27b9a42259e6d5e4722a0047d mainnet-00682-a6b3aedb.era1 +db451ff45d68afeabf0b0230635f246e901c1cedf3280207ac615ff62561fcbc mainnet-00683-19fcceed.era1 +67e85a3ffd3881dd4f3c8bf608e78e8dd3003fb0e52d61815aaa6f0385df9911 mainnet-00684-388b0bdc.era1 +7e8bc25827cdd3ba2e5388fa49d4b3f0fc07d1c02b6e4231a8a9348150d0ac02 mainnet-00685-a2bcc3dd.era1 +c97ac912960f05cd5f6fe586a23d3b0822a5acf5073de8d87af1e892270d3c1e mainnet-00686-df515337.era1 +8a61444d3779778eda326b26ab0d38f92bd5854c60e8287ffe51d90f4310e4ae mainnet-00687-89774425.era1 +188794b31490a304267a019775cf6ee50619885d4a637aefab85c2e589051793 mainnet-00688-a979df6f.era1 +f4c53896dfebcb9fea054ac87fad4ebe6edeb0626ecbdf968e71a94ac03c037f mainnet-00689-33e5fa30.era1 +0f975a96a671fbe2cb3da544eb92c0531120ab966661568470b8d7996bcc071b mainnet-00690-7c95061f.era1 +91c003334447afce06ed484e69166c2d8a80692cb99ec9e223328825177233a3 mainnet-00691-062b4177.era1 +1a0679af4a788eac614047b0c7f7d5286d285ef23d2729518cf05e1e62086622 mainnet-00692-945645ca.era1 +ed2e41823a39f3913774790dd3f7cca12a862bb327243ab5d3d327f64aeee0eb mainnet-00693-8c6754fd.era1 +6a9f6d5784fc19aa2795e0f7169824ce3be94f328a8e08c991c7527030152649 mainnet-00694-222e02bc.era1 +11f48d72bc9f0ee8fd0ed8ecc58604da4c2acd1474e77956111c93b01d19a8f0 mainnet-00695-cebc5a0e.era1 +169be7b45abddc01bbf49a7dcd3a91bf7de2272e80cf08dcdbbb636c23e43046 mainnet-00696-f73fca1b.era1 +f01589a9225cc431608eaee63a9b5eb2af6ff1d2268d50e9abf3aeffef99938d mainnet-00697-cc3b1831.era1 +9959539b491fefc82aa849676da42da17c25bbf7c004ff2889fde60659304d77 mainnet-00698-062461df.era1 +aaa7490ab9125230ab58d21840f5a645460e58c94a50264aacdc41406258edb3 mainnet-00699-7dcae2e8.era1 +b18c1e7c0569f12199080c43ac67f26f7129db745fa82767e9979a6128014448 mainnet-00700-64f029a9.era1 +529130a29dba8fd6fc9423ddcd3cbd2350f3038e75d00ed2932728ddc79b34e9 mainnet-00701-c0ae757b.era1 +1d79be36536d3a481a961ea9d31228a07734a04454258968944ab85a70ff8b15 mainnet-00702-abe351f7.era1 +0649eb04c5f994176702911403dce6e76d9ab9cb3646b0cc9900fd1da5456319 mainnet-00703-ddee734c.era1 +647f0d18ab11581d96ba1ec39a8fc39463b97fe456ffb39b9a38588d8ff0bfbb mainnet-00704-2ea464e9.era1 +d79091de53ddcd1f1428615058f9ece31916858ce935dc0b9faf833128efd8b3 mainnet-00705-9f0bc9d6.era1 +759196c48a51d500c1059d1050d7d11c4019f9a01b465c43c6c4f97d06f2a116 mainnet-00706-58568eed.era1 +fcdb249290108031e8552ccefd4e85d227a1dccfbd760551bde1bb1b6bb07588 mainnet-00707-6aca1899.era1 +b4e811a52bfceacd836304f5e6b2b63d8ca05e417d095d0b81a79d7f07289a3b mainnet-00708-2478502c.era1 +4c24a09dfe7fdfb5d2dd6b7b8043b85ae1691a708f96079d31163427a2f78bb4 mainnet-00709-07426af0.era1 +b222ec65ca7e78c42b025a003bbb7ba4b82a7ef665a8df6f2b2b19ebcd171087 mainnet-00710-a70b753c.era1 +9c9476146babdbf7cfbfcc85755e97c9a1dcfc41cd93488adca9d230e8c1d35c mainnet-00711-1146e2f9.era1 +facfe2ab8f519ecf4622a2a25af984cb7fc8b7300cc18c6d34f6d721bed02dd9 mainnet-00712-560a8119.era1 +20eb96472a2f5a26e5cf3c48cccbbfeba111fa563bad6fc62db37752c3ef12e4 mainnet-00713-54d9396e.era1 +4fa11aa49d6bdd34abcff3b98475b59fb6ff04309a26142b5a7ebe5ff7dd20a4 mainnet-00714-8979cc56.era1 +efcf6d2d45ac3fa094630cf95c03a841956002005fc61a8e282ac6295054c1e0 mainnet-00715-1a583ca6.era1 +f0735f3cfe7e989cc47f4fe90bfbce7f8825fa0283239b0678a0da00b7003595 mainnet-00716-4850905c.era1 +43477645f9faaf6d860e4db56b65f8b96c67133e6833bd7914f6b5efb09210aa mainnet-00717-f510edaa.era1 +cba1ea26f8f8bc454bbe630aadaa7a1cdce945a86ef441627dae86049c836807 mainnet-00718-511c0a35.era1 +11b10200113c145e9c396eb86feb639d753f16c8ac27c5bb568e06d6895b2597 mainnet-00719-14409e14.era1 +4e7715a873ab9019ba4b3ea66cff451602b4764c151a94df5556a70b77b96930 mainnet-00720-cf91e8a7.era1 +5e6036eb5134080ede07fb7e6a731eec2e5e88f220b54e0caffa8fbea6442f77 mainnet-00721-aa869587.era1 +c06d8a0d579be2c487591b9e7e068bfe3b2348ee6e38ea94eb096202b4f79747 mainnet-00722-96e85fdb.era1 +f6f2737160322c926e85fb2dddb66ee382bfdbcd36696b864756b2c69829f23f mainnet-00723-78bf01d3.era1 +45080dca125923a0b07c3539e13dcb431851e1cf19ae911916fecdd8331cc0cc mainnet-00724-d7c27830.era1 +1a072571138c6b6dfb3fc4c89169e4b240a53c3d516fb12158b50d90e1d51af8 mainnet-00725-8859c97f.era1 +47c32c2917e15ed6775575b9ee53139abb572a04ce3c3b502659f5cfeca8a506 mainnet-00726-a705da9b.era1 +aa884f208d403cacee04f18685198ba1b049e951ed9d4c3226c02286e98f0ed8 mainnet-00727-58d83126.era1 +0baeafe4a53271e53c5d745cce806aba8d169839df6f40224a1bb0b924012c32 mainnet-00728-2daec931.era1 +ac3cd8a41130765fa97b54e59f1b61c8f7890c0b6de0ff7bc63e5b960d329888 mainnet-00729-fe141ac7.era1 +403acdd0eee9567602d404dc27aa0aa43dbbe5813e9d07c33c6dc04542fefaa4 mainnet-00730-4ab51ad5.era1 +81f2a1dcce251e910a6b2616235ac1c9718c4d4dee628430c76d4eb67e1e9c2c mainnet-00731-11b0f603.era1 +39d7e4c8d1f909dc9926481ae7b41210fc34fa9c1d3eb8c7d21b972e7f16ecf8 mainnet-00732-3e648126.era1 +a4ca4269db030f9983932fb80c52d86cbee645cf55585f8e96c8310fbdf2e767 mainnet-00733-87195980.era1 +a05161b11cbbd92e96b8734514dae7e41fb32ac53f760a5656d48e500b3eabc2 mainnet-00734-1a924a1b.era1 +757b374c13193263d38ee688ce99be309cb138aefa1382d3ee9c46fe34f140d1 mainnet-00735-34d9d6a7.era1 +e0b1341fd91ae23aaa8fe6422cca6b4136c2ae01f9d5eaad479ed6cbf7dda434 mainnet-00736-1569f88b.era1 +5278b2c6a98464ee7cf44ef2783ea83a7b797278a5fe0dd37c29de437d674b68 mainnet-00737-288181ee.era1 +5d106d493c40c900f9dd36f10f7cbaf382722bf259c1e597ab55bad31d979439 mainnet-00738-28dbb0e5.era1 +ef9dc3b4e683d35dfad3ada4e18074d1aa6eda4b7d5852e932014d2a6e9d262c mainnet-00739-4bd79b88.era1 +234b110d1c89edcfb76b887e7d38b1697a4e6b477521e2dfb6d23cfff7f509ec mainnet-00740-c84ee780.era1 +454006b0104087dd6f2a855b831284641b8ed3a581fd5d22f893ad647799a447 mainnet-00741-2aacc622.era1 +36f9e4340000b17fee5a60aaa8b027f6b6b0868729044fdd348fa956b402ca5a mainnet-00742-165aa7d2.era1 +f2fd1d7559677afe1687761b169792823d1711db640bc8f4c7142b5de856fd61 mainnet-00743-4505bedc.era1 +d6259ca729eb889b9d4a877364fabccb6b6598f996f92ed999108c6e0a8f4b0d mainnet-00744-08785ac9.era1 +951d9d6d312df5215e226ff147e65ef4b9c478357b34cad24fb092c49366ff83 mainnet-00745-6ea3cb82.era1 +00cdc00c7b037f9fec4025bb005dc4fdb10d844abf664095b5624cb121d3d253 mainnet-00746-3ec58c85.era1 +aeed399dfddb49eb56ed6c4fc985de8e1239a0156e304225a7fbf1e42b53152e mainnet-00747-aaaebe5b.era1 +f0127615e787afdf46e2f0e9f521852c4925d02067dc2b53817c2e787a5bc208 mainnet-00748-5ab3b222.era1 +e618e9d6c36cd81075adfd4720f08decd11d117dc729b486e374ba675a1f8fb4 mainnet-00749-27aebfb9.era1 +69ae574192e47b15950c6bfef28c3a35bd96c77c6d461f32e6648cbec47a5994 mainnet-00750-cc08abf8.era1 +5184e0347b27b7c2846a7cc9d8d56f58d1c868c0ca8c750f65d5abf7a92a7db0 mainnet-00751-032ebacd.era1 +73dfcd6412f043002eeede1e22b59fd8e7c2d38375105fe48e2f60f8d2b17aac mainnet-00752-f09c12bf.era1 +af231b7d2be6ca761ce05e0839242505d5ecd15e363b81bdcde0cd2c99326c19 mainnet-00753-876733dd.era1 +edb3b762bf7f179c9415c0b4d9d8b849cd01df99fff8d72350e3aa530c726649 mainnet-00754-f50f5eb2.era1 +c96ad2aabd39d9cb790f32a4c2e9aa24ba8877ce3489abbed79cbd85d261bee3 mainnet-00755-4d52bb12.era1 +5bb0d284e04c58b366933c7ad93b816b60ec6774afd18155f19ec148af677b87 mainnet-00756-0af4e42b.era1 +8cf3c848bb9ba0f512bcf211bd89752193725c03ce60c077d983f82d72da83cf mainnet-00757-d1988f79.era1 +0aa584f390cd3e83d11245e62c0e1f3edbaf89a7b4166f929598f932170be0ef mainnet-00758-c66fcb07.era1 +f4ad0b6868a576f6e670960aa670883d0691a656545c6dd5756dea054684ae66 mainnet-00759-a6242a1c.era1 +faa95dcaa6cf362bff7639586a79001b601b0d2c49e548c2b77eed7f04918a63 mainnet-00760-824af748.era1 +b8776c5583333a6bf3063c06c132b39c363099b3351c7bb44bbb82914cd15175 mainnet-00761-76b41584.era1 +c29deb290cd84e84e59bd86974ae049bd69aa283cb94da57e385c71fd8b895ce mainnet-00762-b3ed5869.era1 +0e0cd6eeb32a3320122073f1ba597f9600d0f3abe0444e7e48a64e92824697da mainnet-00763-713aaaf6.era1 +d85121d80c07bd88b93ee21d95136006971523c36dfb46925254f14775e50354 mainnet-00764-3a6de7d9.era1 +72ef66a9c979eca04f650c54cd1f334bf94a34be6f0c287235960baa10726a8a mainnet-00765-18b5d602.era1 +20cc4439cdb54ece9650382d4360834c7c2b406224573f5a09f1683d6c77bbb0 mainnet-00766-6b5ade6c.era1 +e9a38db7edfe16fbca16a7b44e304bfbb7c7f6fbf230a77de534a380a37cd20a mainnet-00767-a0084763.era1 +73f882b64246e774201d47b5e1f884df1f0a0f8ef92916289292a546b74534ff mainnet-00768-8dc563b6.era1 +4fb15c76d90da3a64468adc30ca86c984fc77f5cc872193d4837bb58033c0b7f mainnet-00769-efd6696f.era1 +7cd9b83f4a1e70031835ae489fba16fb9b117cd00368a6587788b84715d2697f mainnet-00770-d9db47f4.era1 +e74a69adbaf2fcc03ef8effbc27ee37bc6377b2900a8aac1e689ff7634163e55 mainnet-00771-2aa70a70.era1 +25e786ec9a3ec2697b013da805d8e9f4099ceca0cff3c3bf54c4a8dffd242ec4 mainnet-00772-44dcb9ab.era1 +987a384d69b0c8f45108efa12a0a69641d419f50bd5ef58b4115eac0ad4f7a0b mainnet-00773-e4dcc8e8.era1 +8cbd5932732dd2189913c32d567a0c3c3bc7cdbf905f021c19de90e7d747ae33 mainnet-00774-63f82331.era1 +fad610eacb2c1fda9951b16da32c499067c2dbbffa9089affacad6cef75eb1a7 mainnet-00775-f24f282e.era1 +655a4fec41c94fe11f86f7354456de04806fdd2e6c101164617d8bc4dc833580 mainnet-00776-382525f1.era1 +76c4992a3df40f20c6db7dca0107b76805c5f823c26655e74ea4d62776c68f1c mainnet-00777-2d3a5e7a.era1 +d404fdbafa7f116cdd0dbd659eb13a4ae3c495ba31a2301034e0369178b5cb7d mainnet-00778-9a24e966.era1 +23cbfc6d257ac6111ce234a1dc24621e63f3a64d2f9122a69c366bb320bef26d mainnet-00779-0be7242c.era1 +2d3ca21e39e058e9e0fbdef9c8d6f2ede1c729e435bea0171607928b6b5ea459 mainnet-00780-0b8c7a94.era1 +1e5cd634954cb5af5c2026c8168cef07831ee5cc1a354b84c8b528e3a27ced7c mainnet-00781-6e9ae080.era1 +5b39d1a2fdfaac1445d5527ba604911c5dfca84e56ba21547c3d82f3d71ddae4 mainnet-00782-e888e6c2.era1 +eba1cf5edf3a613187567a095dbed18573b7693d84064ee8233697f46cd288a0 mainnet-00783-03027295.era1 +54f8cc69cc158450a31f5e10945863651b92506b6c9ee0388efb3bde946fee1a mainnet-00784-b6efb516.era1 +266195977db2fe1a4e990f73b85b91a15201b6d4d34259dd8398c0d9acf28f3d mainnet-00785-79728b75.era1 +7d14175e688c263b1f3fea0c78b1d753ea8edbefee30fa088e2b3db5a34ac0fc mainnet-00786-0586eef4.era1 +5c848a25b0e382189d63b672a3047f457c0da1f29d7398279042e9ab07828daa mainnet-00787-a0d4c8c2.era1 +1bbc2702d2afe8fe0196739912657171694143266120dcab6a8b6f4eae4a9b80 mainnet-00788-a55feb48.era1 +2c6677eac63b14228a79de2b470c0e87554078fd65ce3b128bc2d3a93e497a9b mainnet-00789-9b95d3aa.era1 +23c2b521567f7faf280ad5c396fe6e300d966cc70c82a2f33495444b55bb06f3 mainnet-00790-4a62280e.era1 +26a010a5d04321387a16aff3b20a38d85e42d40a327610ec7fc5eff8ecb45d23 mainnet-00791-064776da.era1 +ef387e14a6e19a36cb30e3057df93d90680296e6db33f4e6f1d2ca5179d847eb mainnet-00792-e9a29542.era1 +06d9b61a90665ca14338bd691f130cbec6fcbf17076d531c4afaa08eb1dc1899 mainnet-00793-93ac12ba.era1 +6f9a483d559732565981e64d9f30696e9ac41a2af3a60398fcda559fa1b88c67 mainnet-00794-b199a309.era1 +3b7a9aedd26d7c5edb27afb1db0d876cb00ab7f954e369ce6293ffa4fb464fcd mainnet-00795-284915ec.era1 +f352e9f87838e6e16e1aea4133c7dafd5f1bbca965dfc10ffe844a7af8083e8c mainnet-00796-80b8a598.era1 +55f664a64de8eb2f391f3347ad306dcb35650144072053c39711443956c19c9b mainnet-00797-40e902aa.era1 +44650700eb2ed69c8ea01a50ea3d55b88982011ef2ca161bb3ef9209fb0a05a4 mainnet-00798-25bb39c7.era1 +a2527eeb080e317933c7ae3d15b5617bb51eb2ab60444b264d16787678f5a084 mainnet-00799-565a1bf8.era1 +c27e810664eeccdf7611104508fdd016255ada12d8c9e2f1b0c275f684f6bf1c mainnet-00800-6723d6d9.era1 +576eb0468f152ea74036e597cbd655c4656e177cfc9d4c21b731d381e54eec7a mainnet-00801-2c9057ba.era1 +1f0182c783567efd7b08b8eb00955e2aac20a00047b8de80a7aa8518e993b422 mainnet-00802-75e347ad.era1 +3ec2b5d0bcb227dbfb350665400b7668bf31b990307766f572d303620acabf68 mainnet-00803-afb8c20f.era1 +516955f0f2a8cc35bc4bf0485bbe7cabcb9325f93abbed372d9d48d601032cb5 mainnet-00804-472b0432.era1 +c193068ff829f0ce35841c777a390750ce40f069e9cf948bc8aea96f6036810b mainnet-00805-a00ad773.era1 +8f11cc6871e56c446cb3fb797808f2908de4ac225eee56ec069af8e858202fa5 mainnet-00806-4fabbfd5.era1 +1c5b683781c57d0b4117b92c8204e8adc1080cd53e59b7aa16629b5b987fcdc5 mainnet-00807-ebadaa84.era1 +755a72dd1700d49a4190e5fb5d4fac7cb39c7a06531ba16738e8408865ed4515 mainnet-00808-71a5a039.era1 +1e880154f791ae3fa004c93f10f460a67055e98eb8993ccfbed1616596ed5b63 mainnet-00809-2a78afe8.era1 +2d0af55bbb0fe44298351b997063d7f225822141b70d56fb7835219f90e4a805 mainnet-00810-ddc91137.era1 +64737d4dd5ca8dd7b678d5c5e6a5d6afc21afa5403810e8d9ed9068142aa3e2e mainnet-00811-47305f69.era1 +b1eb8f4c86160122ead51c906f295d231ad0966f56f54f078ab5a53925af1d2a mainnet-00812-6492e812.era1 +b3c222d370e3ee3d8aa0246b763a4105ba639c99506f2cb465244e384cdad618 mainnet-00813-9ccf4c43.era1 +dba81e8ae00885ba63625f28e5ad23cc4de38fd8cf70bf7d39c300eb4896079c mainnet-00814-02f878d6.era1 +de85a65021d240a9babaf9119dcb8733f8856b69630ca513f6d01be42b906883 mainnet-00815-e97a4d00.era1 +aec0e36c9eb751b619607bed0dbe90c1ecae0baed021108bdb8875ca16687969 mainnet-00816-13c60a90.era1 +c43fdf019869fd29803afb9b594cf31c287abe5df29a5729d91a8d19b7ad463d mainnet-00817-6f8e5552.era1 +156b02cea4489b1a74986a6a96207c49e769cb9fec3f3623254cf66d15d9bdc2 mainnet-00818-8143cae1.era1 +6f7d16fd1fe7ba3287373b882673d7f8de1b3caa83a979449cb8ad0ca220c7ac mainnet-00819-3894e28c.era1 +2ef10197e0ec1f076007e76cd0044f6012e9478bce455e1c6ab27af5b28ecedd mainnet-00820-97b69aec.era1 +2b571624e519694ac946a8963cc35a80843d2a22fda91476fc430e6323fd36db mainnet-00821-22732c18.era1 +274fe58e0bf337c9af2e66e61e7866937fe5290e5c05580fa0443bb4ba342765 mainnet-00822-6977fa0d.era1 +d10336ec40c300b2967191042dea4613c7ce16d114962dc4245f70391d2cdc2c mainnet-00823-0d164934.era1 +0e7487d0cd7a9273c6e4adf98b6627672f97acbc540f4f752b1f7a6ed5389706 mainnet-00824-0de9eb6c.era1 +9668d2f0fede353ebe778a5916b48dd22521e38c8e424805a0020e73a09318b0 mainnet-00825-14eaae63.era1 +541df6a997cd34fcfea892d47007778a079ec92516b0a53c54b7a17dfc2c87be mainnet-00826-e0848f10.era1 +67176e0ace780fdc4c751faca06aa35b8b897de4fec7ff120cfc2cc623e23482 mainnet-00827-6846201d.era1 +ddca6498e8f12dc4d15a2f0592a7dcb78681f6d4d6ba2db1508bb021c9d76dea mainnet-00828-e89c0e11.era1 +0b1678360a7b7a4d269123cb054c9dcab19eb9e21f1fc7ec4d684076b243556e mainnet-00829-3096af76.era1 +be8f8693a8f699e6b3d3de90bdb0fd907bd9ebadd424e5b7ee2a0e525ce8aa07 mainnet-00830-55e8b4c2.era1 +5d90ca3043f67c4ec0c16aaf656dd7675aafce8146c9a119c7d2ea7262b7ebe5 mainnet-00831-c501837e.era1 +ff9c8780356bc7b44cec3ec9a07e07c1e5c102e0408e3a03cd52ab8203e59c68 mainnet-00832-f7000808.era1 +777a905c9c451f682e8902689ae81d244b955b5ccd7166fee687ac65299e57c4 mainnet-00833-5d73b97a.era1 +0d09a043f487b768767080a7cb9a2999e0afb6f766f1eb17017bd1c2e735129b mainnet-00834-f240decc.era1 +5f7413b54fe8b908d238383ad8aa53557f31d244b3e09835305e89acdcdd700d mainnet-00835-fbd0a368.era1 +f9604ae67043945c772d35f5b354da6027810809745e869af295d1b1d9797136 mainnet-00836-fbd2c4fe.era1 +7e658a4924682a76f2e9b66a2b7cf38ba4e7189d06f8633380c28921787b874a mainnet-00837-8bdc3304.era1 +0c4b2d40b6f42990ab482febb32d7c118f4a884079860696ceed02b5061caa78 mainnet-00838-2a2047ce.era1 +b56d1805a5a2f536c44269940db3fe5e7a75bc5594fd5f2a704ff68db3e60535 mainnet-00839-84c88273.era1 +8efe7fa27a8065153fa40f6363c99104ef10b34f5319c9f480c0f167ce6f3021 mainnet-00840-b96ae20a.era1 +1c3abd6c87a8d771905b6faf2c536241996da762d7499b9b47c04f59baad580c mainnet-00841-5cfe6abd.era1 +9fbe25349e52af63cc08d8d0aa091ae401e935fcb18cdd1f2fb1a4e3b0f444a8 mainnet-00842-b7d8f3a6.era1 +349bb1550ac853bf6fb334c73d6096d94c501caf0f5ffb3b997d0c2a690c7bb1 mainnet-00843-c14d7f51.era1 +825bdb0e4dc314a975be7ec16975bbec2a494c56a8dacb3a3f8adb38a2d72702 mainnet-00844-c5eea731.era1 +621fba64543fa22a6f7d50092f0da5f182eff044cc993b5319c6be4c5f5aee4c mainnet-00845-aea57615.era1 +dacb6a1bb588a2b093473df1061457fb052a703f97dbe77365cd3b5cb1e8bfe4 mainnet-00846-be228f4a.era1 +99c926962e17407596982c55cd9034d5aa32cdecdd9fa24ad9bfccfe2c01ff4a mainnet-00847-5721c5a9.era1 +d1bf985348255c72ee123835be2523aef37106ec34e9d3555f821f647d2c812e mainnet-00848-4f17a7ba.era1 +3dfbee47d98740194164a1da35f778c5e2de41249eb5716fd8b1959a0bfdd258 mainnet-00849-81731fd5.era1 +cb89b3cc922fc3ca0a3634c88ae899f14769fb555af4e93df2bcb6c08a313970 mainnet-00850-c8596aa5.era1 +a5374105029f37804a25ff1fa5cd6fbe17e1c7c8c230e5e2da3dc9926c329395 mainnet-00851-d9d76d29.era1 +69d5fceb5bdb30f0bd0c02e8c7c01a9a06e3603f496add26cb41f02f81d72bee mainnet-00852-3db9cab9.era1 +1318265fc0e49c9549289db1583ad004e718411e8f959d590c3269ab9d58ac60 mainnet-00853-05eacb14.era1 +32ed53a95c655e7ddf5cba1b83f8b06a3ea0f16d9598f747371d580f2d087e53 mainnet-00854-78744453.era1 +3b424157848486554e6bad453e338dd7a770c825464b65e7fdba8c74d41346a6 mainnet-00855-b042cdda.era1 +027cbd4ae8b99476b0c4ebe2a6c164c3055856b7b2c69d0ad1afa8b73ee0e988 mainnet-00856-c3dd963b.era1 +72a2f7309c80206e90129356a0700eea83359cfafea4eb724c1650c139b9777a mainnet-00857-1caf90ed.era1 +cedde5c9900e8bac7d6855b70aebd43094c1ea39d36f0769936622e0996445cf mainnet-00858-7d89c8e7.era1 +e528af9ce07553334ec61b00251670229b142d151e3a5ed87ff8071ff1efc30d mainnet-00859-ec9f0685.era1 +8718ccac4340a9427ed167d0330ff341ea8b5489b4a0d65b6194c50eeb001401 mainnet-00860-608f5138.era1 +7154dc222f0ea9ea1bd075bdc565eafd2a80b2e8d0f74c2550c0068ff04947ca mainnet-00861-bc713924.era1 +129b6ac7dab14ab7ed58ea9055d4e457d2089b356870552cc45f92fd0e384e8a mainnet-00862-f5d2654f.era1 +c4892358ce1ddc2d27c6575534201cce78bbde93bb4477656991b5ff6bb9cbac mainnet-00863-29f0d1bd.era1 +dfe0378cbc98fd5e150e9bd4d9b483902b86393d6de48c87cfb7a6f4478e6e1c mainnet-00864-ba09ed24.era1 +d8e572774bb74383b0b3b67c2390a7752a1291fe53bc503b8cd4dcff72eb0e2e mainnet-00865-ef98f25e.era1 +85fdb6469bd9861605ede2bda3da71688ec2c7c9794a85957845b4a0541fc44e mainnet-00866-62ec875a.era1 +4aa0daf8db04b5f98ea162fbbe21e5b9ebbc4201ec48f14ffeddf9796bf05d32 mainnet-00867-6e38f92d.era1 +f822fa286ce4f488fe2fef1dbd825ef938c375e7a730fd2386d735d4f64f5f96 mainnet-00868-ada339e0.era1 +475a67c9e88fee4153749b7b508ff6e04956786b5808c579597d3ba307a59d25 mainnet-00869-687f70ac.era1 +7eeb7e0e77ccf7e4338c71ed5161ae89ac45c16f6a81c2c6ec7f40d56b5cbc9b mainnet-00870-69305b66.era1 +b87586f0529bd9ac75cadf5872d01e97a128bc0468ade8177975a5f75c9c6146 mainnet-00871-dfb48357.era1 +e1ff274cee47442d0f6a3196f981ebd336279c9ec557a7534c29fe3dcc970635 mainnet-00872-1fe0bd68.era1 +118ab69632ee10241e5713c0f6d8f2093ec87925913718e004d3d9b8ad4efbcb mainnet-00873-6754774c.era1 +84c7fbc68de4a30337119a8352fa366afef32c63b6e3e6ca6860c904c82552be mainnet-00874-89ed1e98.era1 +390950d9c6a9583c14170f406278c32300e62564c8638b4c4933a35c444e407d mainnet-00875-918e70e4.era1 +bcf535b017d33ed06f70ace1300fca8eda94b078ad584f8e23ef90b2980a9966 mainnet-00876-b174fe36.era1 +c672c2865f7edcb16a11c7799af76a3ce654810e0fddb936f429a3959f582b63 mainnet-00877-1ee06c60.era1 +9d280918ca66cb1b75b6ff39abc1953cd866d40e708be09ddc29c8c5508f6c11 mainnet-00878-acf82dea.era1 +4025b2ff2764c1093b7b556337238b4dcb79ee20330e884918b9d0d159fd4a2b mainnet-00879-194ae199.era1 +e28cc9f4907f77f63c1e2098e3100d3bb5a9585a553adc860e31fed266e826a1 mainnet-00880-88dc77d7.era1 +48c57783de2299b511ad9b4b3b1cfaf24d5b0e864f82ab0dd620952dd2000ec9 mainnet-00881-291ee430.era1 +75132edf2ac9f031bdb28dfe8bef1fc628262135b2d57cd70cc28c1257fae015 mainnet-00882-e0bd01b9.era1 +4c576b4ef7eb6ee53792c977fe7e73d584efeeedb968ed005ced2356f2babb3a mainnet-00883-24ee5653.era1 +9a3ba18e1794c2d088c6314b9e7829358d8a6a7ad54cb04a6d0c7b7665efa57f mainnet-00884-f4649173.era1 +3164f52873eead3c508a80e297071ace74b7471209770d0eeed4b5c2dc60fcbe mainnet-00885-18be5807.era1 +fa98b03cf7ced8a5e106f6cca26e0f91a1eba337f55241952a056d47d00c65a4 mainnet-00886-7b8e7f87.era1 +de1d232a777550f9efcd6d42d03aea8cd8a8dab7234989a5a5f8f0e6f3df3baf mainnet-00887-ebfbdc02.era1 +dcbc95e80ab179d461aa8fab2fcd1a47f3d9160be1934c7f1dad4e67e8497015 mainnet-00888-2911ec46.era1 +ebc966ee429a98abc65a1acc8bda0cf89846e908fad41229d133fee188e8f0c7 mainnet-00889-7bc66f0a.era1 +e1d6125e7cf2b1058e3b2897b467be1d4597855f52732bca87c0b8e67b386de5 mainnet-00890-de4cc0f1.era1 +137ef3280a18c42f45a0e5b7a75ea5613ac9e0408a7ff89451dbd9e089d27a1f mainnet-00891-1aa1a5b9.era1 +efd3e89f05487d7577a02ec113d6d783ffaee002823eba325a3b9221f3e2bfb6 mainnet-00892-b5354846.era1 +6fc953a47233f82b6448c9d62de998aaf4de47bc86baea1111e3673630474181 mainnet-00893-75d76eee.era1 +c4d4b4ae18dfdba3c50ab34896ec4314853526019d7a40af437c96c9276e0e77 mainnet-00894-81aa556e.era1 +fec02056e20385d7a07b8d138d6060c4e034f38e42e1b70eb2b0f482daf35a07 mainnet-00895-47043527.era1 +a21ab7e602030f9f66efe79072a3cc41eb08df50b3fe780f2a3975195e4e1a99 mainnet-00896-1ab5749f.era1 +bb6e1cd24d035f6ed54c378f1f45d5b8266980309ea97e97b7992f2d4be7ebc7 mainnet-00897-b81f63bc.era1 +7bad241161c5205162bd908cfb3a4a70fcd45d14422cd218676b153d9765b121 mainnet-00898-ac96c902.era1 +fd2a6b0df6b2af60e1b85fae56526460285c589b008044144e0d1a2be09850fc mainnet-00899-922b1cf4.era1 +d24f52be2d507c65a11179fa7f8792e892ee2f0d50bdf798b03a190cbd807195 mainnet-00900-0f8ce285.era1 +4d66f4166981e486be794971c42d27251b873681f53c1be0342cb2b2219fe51f mainnet-00901-f6f06a90.era1 +46291a80c3c36d692c14fd2ad98324a0c1799fb186b7d7a46f17a330ebe0c5f2 mainnet-00902-65bd2e95.era1 +ab933ea7198ffbbcfb8eecdeb5a4a79f38bfb2175446f7f0e11ff5e46a86fdbd mainnet-00903-3b916edf.era1 +bf50a0862e08e65b515bb34cf467ec2f1877011f91788d5da85af375c5928125 mainnet-00904-2ebf7c0d.era1 +9fe3d97ed06c05719278c081a0ce81fc9b90b60f4364517cef837e02bd1aa871 mainnet-00905-9e7868aa.era1 +ada9399b7d3cb60516a05e8e2f8e82f53d67e50191834c3a07e29bfabf32bca9 mainnet-00906-6fe8a5a9.era1 +59e1bb4ff7461c2613f75d9b8f4ced46df1090fb83073b4ecce9200aab342347 mainnet-00907-fc681d3f.era1 +767a171cc735352d2a21d48c0acfc59094617f850ed0a8814627cc0863e8cdd6 mainnet-00908-65f73397.era1 +121d6b676ecd1d763e18f8569049ac47b615d6ace0d5beab85ccc9d5b34c07e7 mainnet-00909-38ce4f9f.era1 +8e0c3de6b2ba02de171f9fc08ffcfedbce4c5fe31115fff19d7c4088706887b8 mainnet-00910-d44a929f.era1 +c27791d691c1fffe75344b160b441986e09261dad084f892663c2594b1316161 mainnet-00911-fc91f464.era1 +1b7a3b002df8b6181573d4ea657abb3262c62bb3db209b96132a0252e5e38861 mainnet-00912-9acf8a7e.era1 +eda9aa0912b50a7f9cbcf16e7f452bbca9460dfccec5609f38ff854316e48374 mainnet-00913-07907337.era1 +571a05a8c5c25983a338bd9cd3498cfa4c60a8c671bf3817cf1c693cbc80621a mainnet-00914-822dfb1a.era1 +5cb2b9593e4677323ec2d75bb76c3d9f1a9675e1ec61872f4300e890e646170c mainnet-00915-62602cad.era1 +63e4fcefebebca610aea69c2210aca0f58882e0eca79f8c6cfbe5e29436e0295 mainnet-00916-8b6dd223.era1 +f6c8b5fb2a4e3a963bed34909902bf4584f85c3447bf545e24b0e6ef8e73aa57 mainnet-00917-b309c469.era1 +a95f81ebc9e973ab484bfc2d3fca9585641ed9e1e334a94f3c3286b426175441 mainnet-00918-8974583a.era1 +192024c65b05a4d2bd1042fad07b4e61839e672a1e81a52773fe974c365be55b mainnet-00919-d139d7b4.era1 +926ad369eebebbb0d7a40aa54f15d4c2cda4c9c1fb3360504233d2e8245d8747 mainnet-00920-5b83da49.era1 +efc26906d93119cc50eb15775fa8978ae12d6466ca140fd1e2f62c0e051c8ec1 mainnet-00921-7a62f3b8.era1 +0b88d2be1ec743ffd1c2ffb962c6523e4d5fef009a201280e6a9fa5890085dc1 mainnet-00922-30f2071b.era1 +e5fc818ff8a23885d56a380cd6e9d7e2728b7126ee1362bbe5b6633ccf8e1115 mainnet-00923-9f05e151.era1 +9b1f50c79fc88f347b5a974810ed75cc9ee256686135cd57dbe943aaaf89dd5d mainnet-00924-8d0da501.era1 +76b98352808b1a455c23b302047b15fca7fbcb9a551914472302850966e4113c mainnet-00925-9de1930e.era1 +7ca90c759ebf83ef3c983b061032488895a0b134f62920f55d16a311ce087dd8 mainnet-00926-ac17e41e.era1 +e4d9a82a541fca599acf86184fe54b6e949ee6c9157f94576f3cc097f86c2dee mainnet-00927-ad6865ca.era1 +b0cc10fa6661cd4dd7970ca05c098358d671b74767cef13b46c6a3c7b6a23785 mainnet-00928-3feef311.era1 +5f161190ca57d017f5a901d1fc17b510fe2cb06a9463bd1c53a38977ad2f7c29 mainnet-00929-6e2d1f4b.era1 +df1fa99bf21a8e99fece3e1d5be69f1d87e6bdfc6f4f2ae164b616a692c672fc mainnet-00930-228684d7.era1 +8dc902f268d0879ff3dd2ab5311b6770677af4059c9dcd7ac065633b7a619311 mainnet-00931-2485471e.era1 +22b6ac2db24272183afe4cb1c082765b5fb6d612632fba7f5eaf1abdf5b1a325 mainnet-00932-f2f69e07.era1 +91ff864c90169f8b32be834d74026cf6e661d65b4b8f4833a3d06d27876e46ba mainnet-00933-44eff5ae.era1 +b870a45ce77aceb77f85f8409f2d9fbb5253852d2b00e4832957b94680d1e4b2 mainnet-00934-ac8cf5be.era1 +ae5fe657129b44a16a75fb44b9d677c0b0491a6eadb26f14cef08fa8e1c5f710 mainnet-00935-c052cdd4.era1 +160287eece33d1233317b47d943692a55c3f1a1f1be7f74a30a9330cd1de4cec mainnet-00936-0d1ce1ba.era1 +254785beb70cf70428f860f264c6c0e6acc3a1dec54ea55abdc5446675d6ab86 mainnet-00937-20d08362.era1 +f413c0b34ea5ffe18cda24b6c47dfc331464946ec2d823fa69fc2ad930acc265 mainnet-00938-fb915a95.era1 +b4420ab136b9747fbbe43d40f6877b95b630576a0486efbb4bc6c39c0570a999 mainnet-00939-2d5f2cb9.era1 +9674ae27b0f8066f265ea8b4a3eb72bceffdd519a85f5c46657889cf01966c6d mainnet-00940-31a360b2.era1 +a913eb68f537131b434eb6dde18efb3ac7f7cf1cb1f6d6c734124e13a81aedf3 mainnet-00941-6247e765.era1 +a12a0a421cebf730486a4fd64e229cd7db1973bb9333ae001c12cc08dff96430 mainnet-00942-c352aa92.era1 +0ba8f136af56f8191059c1ed11d4746bb3cd0089324d6e17631c5e51d5e36ade mainnet-00943-b8b31db9.era1 +44fdd29605fa3cce277d80ded2197aa897d8f6ebe1d3710458ff3636a02d5599 mainnet-00944-2a8be083.era1 +369f0ba252ad601864d9892fbdbe4bb6566849c213fcf8b87c690d14f61288a1 mainnet-00945-80961bb9.era1 +87d56afcd024694fd0595fed8a6c736ef1bfd9cae4a439698f5713adff6e9458 mainnet-00946-caefe64b.era1 +aabec04e13481a949bcc0e702dc865d4ffc3059886aa31bf8b6853479fa8ddbc mainnet-00947-ccd88aff.era1 +fc8707c984ec97d7cf1dc937c8ac1d4afc655aecf05ad523479f4e65d187995b mainnet-00948-11d91c25.era1 +38d4814a35cbe059eef3e6d7e66c6f05b56406a1f66c344b04fd67c5b0d6bbcc mainnet-00949-209f845f.era1 +2ba49a308d695c35548b8935ac0c224bdc656db3021cdd4722d554a53fa733a5 mainnet-00950-4a9dede7.era1 +26face4ba8260c69ffa7ec6efce893455a0fddda9ec81e702c821f1ba11fa1a1 mainnet-00951-6493fcf8.era1 +1e78004872cc834c2d92b4b9daeab61277c85a8e0bd135b15e2b12268e72f628 mainnet-00952-611a2c46.era1 +d43cdff38cbe428e0f177bee43dea616c407df0ffc16fd31f32d6c1b962fc20b mainnet-00953-81e7d017.era1 +7cc671fa8a9cd067a420eec0251690d5773937ef01d6a10428ea0fc30ed978ed mainnet-00954-19895bb2.era1 +cd24f28447005cb8c014e30d429ebf005e05f31a6b64c4071f81695d05ad160f mainnet-00955-443f9153.era1 +64e0fca3590d4c5beaac462033a48514345f7292fd1ebcfb690c79a13c0aef83 mainnet-00956-3dcb543b.era1 +12d96b92e2b1b331583f5b520d38b1b2e65fdb24cc4cbd586d5e50eb95bb8b4c mainnet-00957-a2d2aa39.era1 +e6092e6ba5a45be6db818b86cf03d63b13e7718ad02b8815862f59263435338a mainnet-00958-24f3f044.era1 +4113dd29011e08d6ea70e08712d69ca98c99cd77788a45839b6739b0f67e0ad9 mainnet-00959-8fc647c4.era1 +a90611c78f0fe1a3f460c8f11ef47c5357677cc02381441d231ee5ac07430b6e mainnet-00960-680241a4.era1 +66727a8881ca4c719999119cbeb6324177ef95cb8063b92b4ec59917ae37dccf mainnet-00961-759690ad.era1 +cb3c393d014ad5b817113f3a6ea5e6ded53df7db2e3830405ecd52463c028bcc mainnet-00962-12b37dfb.era1 +91f6d92eb6656777199e960af9318ab4c5c994fe582d38df8cdd40e6270eaf66 mainnet-00963-2b4168b7.era1 +731983296d9b8ef3bfb2b5f47b709146c22f1564b9057135a85dbca51c76c52a mainnet-00964-a7136656.era1 +b93b2f350ed9e3e1fd42dba9aa328fe3abe6122c1d421c3393ded798c6e609ca mainnet-00965-8a62b405.era1 +29d762425352d04e8b3ed89a9d0de9994524af5ca224cb1a574feb575371c6fc mainnet-00966-73e45b2c.era1 +227426426b25320eb31e6fc556914e27f88bab1c0cf93c3c7d3450660f1a7e2d mainnet-00967-39942459.era1 +f5c723924ca804105153c00c2aa9d5e38a67499246b81c6daafaa8424006b12b mainnet-00968-dce8aff6.era1 +08f52f2cad8b332ce802a7b43ecd0667770044e327224e877dad3ec9593d98b9 mainnet-00969-49be4756.era1 +c773e4c1eafecf30ada6c33610525efbcd8df74696b9d169794648620adfcf01 mainnet-00970-68c57c6a.era1 +9723cd64a4d5a894b2dc2952d1b264cb6dd96996d4e1104b68b0a904a2c6310e mainnet-00971-c4f6b046.era1 +85a606fe8e462595bee1085c3ab7f587e075c7f8b1b19a0f4bf4c9320a43968c mainnet-00972-13a7fe3f.era1 +7bc56fdc61c327d7d4e057b802290dd5f10c7d76d31cac193513c78f65da9ab7 mainnet-00973-135d2ae1.era1 +4bb6a1e85bc267f1b72d91f79ac7f66fe4df1e53205ad22132d3187763ade96d mainnet-00974-922bb3c2.era1 +30d549c01c8a292b7321796d4f3266f2f7e142e5410c19eab04b6a444be3f0ae mainnet-00975-27b6441b.era1 +17f8b5f4a153431f82836afec6e67bbd18eed207911aedd74862041feadaef34 mainnet-00976-63eafa02.era1 +55c1230e48a49eb9f50536f5e7b7c0d3ab1806066c76df8af2cd75ce0fc7d8ef mainnet-00977-05bdc732.era1 +9f4bee6308808e08e34188ee93a77fb167221aba4c9793f4bff87fd0162b2694 mainnet-00978-95d7750a.era1 +99f0e262ba3ec8ea549cdf0e15f39a1b36e69593b3ae2c70b98a584ec54333f8 mainnet-00979-8cf0d624.era1 +5a03ca9953ce0c35e51a25bf84f3ad95b9b97d736db2af7a4a2550791cd73891 mainnet-00980-a8768f5c.era1 +63b7809c76fa5f72ae92dcd42eb2f5f9cd7a24a2fc7951ac4f1c51e840360fc2 mainnet-00981-c4e8ddcf.era1 +8f4bb2e28111a26adeb4e9ee0e76a85b46357821c44597a12342f23303eac05a mainnet-00982-d4ecd7c3.era1 +c434b12269ffe378fb5bdae5943d4e34eacce459d934ad3c03490d1fc320ba81 mainnet-00983-d39b640f.era1 +386a66ce7a9c92fd26fd45ab3d25642c15ae9054d20cf82f499026350d13563f mainnet-00984-22592d52.era1 +9dd47c3592dada95175b944878e6b671d21046c677ec334e7e8dac02b08ca2bb mainnet-00985-e4e144f9.era1 +e5d7bef7c30a51b441967ea6df0df649c6f4d449c5a6bd9f07bf37366e2daa37 mainnet-00986-b5e7db59.era1 +e47c38f443c8a73c304cc6e04b73e846ddf2bdfb6f41218b9f0fa8e94a4fa26f mainnet-00987-9316c767.era1 +5fd0592e9cdc55d79992c274174b0f85b7ee5c584fe536398cc47aa344104b61 mainnet-00988-871302ef.era1 +4d42c4a88e1af0974887663d9227e30b9d5be4a8d988d70170e0a619ea2a6e2b mainnet-00989-1c3a7616.era1 +e6b3797997eb717ea44a6a9fec06ed1728cbaa97f824b4027bab6f2524d61d95 mainnet-00990-a666b389.era1 +61692c49a9f2a1df764b1935198f2284842ab57b921b765166e45e0110bc1ba6 mainnet-00991-3154c955.era1 +7dbb7e563b116d322c725eec6bd232c57e6350c39325ca287caf9903c1b3112b mainnet-00992-d078def2.era1 +d42a759bed529201dc3b5246c6bacf33db8347573c3c60bf869c26295e36d3dc mainnet-00993-6b2615f1.era1 +aeeaab06a62c01aa287cc2604052f5779303d850191c69ad445d706c7f5fa676 mainnet-00994-6ed3f90f.era1 +f8c136533ecf07678c9f0394cfea628e8cda6e4e17758b488cf953691c2f3d9f mainnet-00995-d3223ce7.era1 +3c13ab210843321c30caf84af68b628ff4345a1fc0595b1f01b32417842c4f07 mainnet-00996-016c769b.era1 +158517c5ff036852a86cbb659cd18ce59e01c46267a55b4bbb16329ee4703493 mainnet-00997-e19a4c9d.era1 +b7950092d83905626099cdb64c81bbf224ca0728dcb4dfbcc0ccbedc7ac4209f mainnet-00998-36c9ff39.era1 +4d96eaf7f23db43fc8260e00a20f89bc8d0c9dda56c0c88dc32dc127cb617a81 mainnet-00999-83c72fa2.era1 +2030ba76226df88d4e9b0141702bb29702d92ff80f39af34caae4d58feabf070 mainnet-01000-ddcc6036.era1 +ca961a71ecc2f608ec95c2d3cabfe722ba69a242c8830236121110ae8fde87cf mainnet-01001-2d0fc419.era1 +e8e5c0142ae6d8e73fcdb9c108aaafc0cc99283d7476d9f21aea1607adafe76f mainnet-01002-f69f7b39.era1 +c5e7d9785ca37ca68adc460ae649854c1d529ef8f90263d00c55386125f880d8 mainnet-01003-17632710.era1 +6791a5fb4f3636e9a7f503fe8cdebfa7fddb4835f587d54db7ea7f3fe26fd8b3 mainnet-01004-fbfc0216.era1 +9f059f87ff05fbcec84a85233e0b6a576f75a62f34f98005bf58c858fae09e7d mainnet-01005-584687a4.era1 +6f98e878cb0186b684f67d18432cf4ffc504b8cffadaea66b4b886865c764208 mainnet-01006-df8970e8.era1 +6389a787c67015adaf7b3e0aa495192a9dee8e795f73339aa8b5c48c69f04252 mainnet-01007-2fbbff92.era1 +c06ed975ced7957c3763954b5e79f86fa3ae2333439feadc0ba26b97b1613c11 mainnet-01008-235c9a91.era1 +96cad5272aece888e7390b8ac170e14556c1b27d021d5b7d17c02a75a3087783 mainnet-01009-fa09b4f1.era1 +064d7a29cac16e87348ea22c86c07b099b86f806d37ad5a8640e8f4420913d97 mainnet-01010-3cacc95c.era1 +99093e195efe2f0ebb023ca172a20bc3cfecf75d4666352f14bbfa4f693c1925 mainnet-01011-dbcb3c64.era1 +168f113b3368eb2df264ded3a88e928f8eaed9aed6219988e579e18b59f274c0 mainnet-01012-6ac002dd.era1 +eb4a448536a1d180da7a26077224ea0c70c56e78cfd3671d8aed75cc984110b4 mainnet-01013-dd1763be.era1 +f6284ecbb3db7c4579a8cf2ce0e37377f9a291f378722af69d8d854517f02469 mainnet-01014-c4e0e059.era1 +532f119847749a5b068777293af5d094f047f75b7fb30c7b0dcbb2e12625e69a mainnet-01015-d2d13e5e.era1 +acea5aa287f1cdb1261436bf28f4d29b22dfd2ba3f038a8b6ff298fec39455f7 mainnet-01016-a93277ff.era1 +39a66b30e7588c8f5558863042d90ecf0238f278870ec95cc6f92a7a705d0175 mainnet-01017-019e6db0.era1 +cfe2e6ecea6a40468ae53f0cc8486981ad3eac40509b2bdc101f8b0d69f67b80 mainnet-01018-763ea921.era1 +4e1641b989a482e9b6a70f6615a457ddd434498f7fb4389efa17b5a13b692509 mainnet-01019-45d27951.era1 +821ebeb97e8ecd4cd2e79fc64cf0a8082b38990710e39861071fbab1dc631ae6 mainnet-01020-37e8f37e.era1 +f0bec9191390d1aa416dca456adbfe372d3da587c0405893eeb3cc7fdae859e3 mainnet-01021-6654a92d.era1 +7759d1bd02558eac871d5a783d5ffd69b6f3b5635fbd20923f38ebc7c67e96da mainnet-01022-b81a65c1.era1 +1162121637cac8aca3977dedcfe29083b7807f921f74fcef01911eed7fb6c549 mainnet-01023-b72e8700.era1 +f6a87889a36ab17422c8dd9262036027ae00a30ab41b319598b85bf8b0ce5242 mainnet-01024-75f6d852.era1 +56033649f9045994d5e5a6b23aa4705cc907882b4385915e2b7d9f4820e10af1 mainnet-01025-cd13479c.era1 +f84df05b13cb4f3603f50b952e7da992e35fe229771e8831f7237006bf1d025c mainnet-01026-1ff6a9b9.era1 +0347df0ba24d97c325e6a5100c6ec1a8dd2b62a8dedba16dfedb6cdc77b1a237 mainnet-01027-6c76c020.era1 +217b9ecd8653cd56735f82ec13f9f9b80f87571fc4b25aa0073f08ec99848156 mainnet-01028-78f99056.era1 +a4938dd48c02ac77af4f70bfa02a805fa1ee24ad0148d7ff3b209cb6f2c56799 mainnet-01029-3dcb5e2a.era1 +c3ae2e4ca70f6eaa23f00ea142d0316e149ba6ad72e4685ccb78ac9dd2fa9059 mainnet-01030-373e75f1.era1 +d68a4f4659203db89c939d227357c2f875973464abae8a02a918afd296ab5a4c mainnet-01031-f06e62b5.era1 +e61a71d2aa334de5122cdcdc4921fa597fe516c78637637c29b54e14b5980e28 mainnet-01032-3f19793e.era1 +beda23a07218acf026ab4de706e9c8716b8a3ba052d867f24eb151a7de34b174 mainnet-01033-a9765c1c.era1 +05f6f06eb10562f992c10268235df7caa2b5bce994fbc9744de35d4c56fd333d mainnet-01034-1dcfe017.era1 +65f03b88c05b89fe7793fbc0ea3a1d7b403937eab092b0b63583d98c41354ad8 mainnet-01035-946b550f.era1 +74031d7bc115ea6c526773670dbf0c40cd638354e174dd53a993a591239e5cd2 mainnet-01036-b953b4b7.era1 +75279c9f4d8e6be5db40f6193afab02ef695d7aec87deeabb57aa3405785a57d mainnet-01037-8356dd44.era1 +a1e60f79dc9971780b6b71ab9ffb988dbd9fdcca2137feeb746615c1fbed6ad6 mainnet-01038-3cefbeb9.era1 +7f3629ad6d60d3bcadbc87b2d8f89ae1997772c8360f545914e5069442c8a963 mainnet-01039-4765ee42.era1 +a598e383070990db48c876eddcb5901d3d9618a3f2d86d67a169ca05c9eab1cb mainnet-01040-c559659c.era1 +8bd6ced70e2b8d7b666975a6af26916921fa567e85cce68808153c75f510f08d mainnet-01041-1b1f9767.era1 +736c0536e6a85b59921dafb87d0e6d9f1378dbffb080c2faa51d37abab2275a5 mainnet-01042-ed5a8fb5.era1 +700a4bbc14266da52241307e5024adc526db1385a0a51b930968ecfb18854f62 mainnet-01043-a396fcbd.era1 +65c75391e62218324342a8b79a1e862c61b9a19e80aff082a8d67d2ffaeef4b9 mainnet-01044-33bd34bd.era1 +aad19a6f122726160f36e5445a697163554c75602e40b705228441b044865811 mainnet-01045-e62bdcaa.era1 +52a3b2e210d69846a3e6c32520107b5ed7afac182fb097cf687d83e45ab3edbb mainnet-01046-37db60cd.era1 +860b139156ce093f74218560c8babbcf6894cda0b13dab72433eda787d79a5fb mainnet-01047-d02ff344.era1 +cc50c84bac158219ef04eef7190fdf4bcc4ed9a467e213adad06c08b59f1a6a0 mainnet-01048-27c44206.era1 +494dd65f9f69d7dc86b98db90f12db587d62e5a33cc2e07e3d0cbf7c3c24f89e mainnet-01049-d74dcd43.era1 +97059495bf3a8efdaededcda73ed9f17e212c9094b54a229431b5943c6ca372a mainnet-01050-583482c4.era1 +db4a2bd13f3d13d13ec7f8f4b08cb95b3a0ae8d3e96eeb3363596d4038dd5d0c mainnet-01051-b1375fb5.era1 +d484e0bb8feb94aaab82fe78ef2ec3a78ce97f547db8b1b706a3d26b303f411e mainnet-01052-fc68a5db.era1 +56bfa4277e67fcde394721e9fa3c002376389a35a25785d9ba681d71b3cd5b4f mainnet-01053-038d0dc5.era1 +337026169261de6cec5708dfebfdce9191d66220fe0c83f59e5bb44164411ef2 mainnet-01054-fc630d10.era1 +6a1ef87c494b74d34f2064c3fbf5bf9815b59d717b326c61c248dec6a10cdf83 mainnet-01055-dc564afc.era1 +0c8e44d6b50903a639b67f87011dbd486b5cb19eec9c1172784173df352992e5 mainnet-01056-75fba5d5.era1 +0fd44ab1a99b65b3a23c89482f3a3bd4930ed1cc063aa718bbbedfcc38c38ae2 mainnet-01057-f2a347f3.era1 +9117c72dd287b56a50613fe0c71569792966eecaabe526e030418e0ab493b91f mainnet-01058-7e00f70a.era1 +ae5c3353aea30d7418921434a638454bf9e17a8dedfe8fc5a7eec0c761a30113 mainnet-01059-7c557845.era1 +44235f35b9dc76e823e7d2ff15bfff8bc004f3cf30615486a62777977ff30553 mainnet-01060-d6b98869.era1 +9d4003643418a6c2f941064f20595e970077cb78d0a8ba97ef84cf1bef2f7cec mainnet-01061-7edcc464.era1 +280bbe45db8a424df21a6ea4242fb2ecd9b63c0211977bd66d5eb56961c3336f mainnet-01062-84fae3df.era1 +eabb0d3253f23668972605d4ded167862f1868133197d11e668e7fbd98ee4b81 mainnet-01063-97a50adf.era1 +643d1a50e895224b545d57a0e3667e694fa17d822946b3d235686081c669bf46 mainnet-01064-25e68a39.era1 +741ae08f901ae74a5e507906f79ed3ee1e0bd6204469736a7dc8a769a1fcde6a mainnet-01065-88ea91bd.era1 +f28e396a734f6766ecd32efaf640ad83f1ba858c1c101d9e50b665f444de42fb mainnet-01066-77a58ff5.era1 +fd291b0c15156b885cf9af594af329c8a2901ef2d5a498e711c1d51bb03f178a mainnet-01067-95926dd9.era1 +88d01100df01cc5680576f3bc06c6774f5fb20f9f4f176c35a4be96631297119 mainnet-01068-9e4b22f0.era1 +2a5d4e98f1adfb8da0f123cc6d7aa30cadc0088f5d88e4f4ede083997a447880 mainnet-01069-5451d56c.era1 +6e8fc5c611fbc0b367b0f24057c13d190cfa20b601dcb76ddeccf90ef05182a2 mainnet-01070-dd746cbf.era1 +8e5078c90f147cc6b2fb870b74a2f8a7e86ae2a9bd718a418e43c9017c94de18 mainnet-01071-e7162b85.era1 +1a76ae6d39cf9b7bd23355cbe2bd0918adf70280b73f425d750627890d442da7 mainnet-01072-a0266c31.era1 +ed7229b26279376d6776d4eee63b3ec7b0df51480a07b87305a847d2e320a2fc mainnet-01073-fb390415.era1 +709d9e99da9db956efc547a8da53b1259cf0aadd1fb20fb4fa15cbc38529aa19 mainnet-01074-7d668fd5.era1 +89951ca75c4c605dcf7dd333ef9b260492cda7b34a8fea430f9344103298bae7 mainnet-01075-38bef7ff.era1 +3d68e0261715155af12b191814d8c6587e2e54f8f6d7cde62b3c8d6502fe65e1 mainnet-01076-55f5a07a.era1 +57aaa772d4054832b9849f5b22b685ffe28819b413cf54060d878834ef60bdf4 mainnet-01077-61a13d92.era1 +caf6c5aa2d02ff166a0b00116e8edb60230a6a874155673e02cd2dbd0a54b236 mainnet-01078-227e7127.era1 +e261e53961745ba2d5ab256dc1576b03fbeeed614fbd4f9bcc44344aa5aca997 mainnet-01079-f1a39e59.era1 +645cbda4a151a25566424e85d6c47d42f2579e2af705ef35e491716346e5dbb9 mainnet-01080-1b7d0990.era1 +6a1383d5b385a1814b7bb725924ff0dcbe5b951a3648cf2041ecbd960cb373dc mainnet-01081-679b4359.era1 +931dfdd43061fd1c92112416ed48b640b35fef0aa5a16f497f65e594f8ab3252 mainnet-01082-5e7dea25.era1 +3c123d39b3ca6bb4b94345b08756345c6e87904d5a91cf1d45ca0112c4ef757e mainnet-01083-cdcb8e56.era1 +efe233952150d5d9384586b5aa291aa810fd28d34beabb3a14dc3fbca8f695c4 mainnet-01084-5f2ca307.era1 +2d785c18ebbb9c32fc274f34c9728aacb027efd4e8b38df7e610ec90fce056f1 mainnet-01085-12230dff.era1 +04337221c9309450bd5e32ff4ca248046ca14534426e91b92e592ba5f45f596b mainnet-01086-6eb5d461.era1 +81c6aa9d6ebe238ddda95def065ed86b54f02826b964a9149c1cad8671570fc8 mainnet-01087-45541bfe.era1 +9711c653391102114ef0a91cd9aa3b1ecbdd06efe48b0f6eb9bd4103f8bd280d mainnet-01088-09f2f43e.era1 +0ae82b02b1fdc71b22fef74ae5f15f3ca52227ce49d6488c470ab5a968f7563b mainnet-01089-4519917d.era1 +4929d107163c10d2399239a9652b31046175b9b3a56b4e4cca7a50829cbb9725 mainnet-01090-506362e6.era1 +1adb8982013063f3f75c5a9658353c1386ada4d77251fffef4d1c24f8625220f mainnet-01091-408e7c24.era1 +8755aa4dbcc94903cd22788a7701cdcaf1acc7b60e7e33d1f090b2a3cd56ccba mainnet-01092-4f1216d3.era1 +fe012d19b6f24004b9256f21faccbebffcee4d3162bf3a3be59ceeade8d5612e mainnet-01093-f7943fda.era1 +67d801f711c55e287c0b864fec6e60eadcffe4de27621240e1d54b8152f0f5d0 mainnet-01094-a2458aba.era1 +9629286e67ab8c6b315ae09f84d249523dc97eff653ca95bd29f98649fd07e70 mainnet-01095-c3174a59.era1 +8760cd2f788250b8fa559ea7d701749edac84afc929c658a4b91b87f58d4ae19 mainnet-01096-5475a30e.era1 +17ecbaab8c991bebbeb4c0b57ea5cafebcb4053958d72efa03885ce44015946d mainnet-01097-d2ce1e42.era1 +8192603d05ff32023df5a9b79059fb456c8f846c5095d166468d6554a8eb2910 mainnet-01098-5fb12ec4.era1 +f8fbfba63a81a2bc092261b01ede77af006099d11d11bb463d620908daab8b95 mainnet-01099-1cd92052.era1 +5906280eb0adb9b57fcc3b9a30aac43785816aea99176b98ead4aa2cd790613f mainnet-01100-22b095d4.era1 +2961b929b05ea871114f1992ea903702830f62e6690b64b563472ffe0701a14f mainnet-01101-844b63b3.era1 +e265b235b9bc18f193d6b93444757aea34fb0b65eb17124e0a7018b4244e0322 mainnet-01102-bcce4dd3.era1 +2e998dde589e88f2b5a444f47f445a2881fbd9ac44243579c78ab16086534cfc mainnet-01103-c9711792.era1 +39079368520f97896290263edcca5ce219733357ceb079f59a8e7c41689c4318 mainnet-01104-5035027c.era1 +98e3fd0235e76beee860b0f7cc698cfc4f6049a95ddd38b2b6ec7ee52d15b8ed mainnet-01105-9331be3b.era1 +b9ebaab58e96a52061462335bf23ed93cc0be2a0b69276b47922b7f6e0c2e4bd mainnet-01106-901078cb.era1 +c7bc6484c0adca1f6725408dfba43a2beb541c89254ffb757ece514f41b1bbee mainnet-01107-f8edc0d4.era1 +2436cfccee3bdc946b849043cc3823347f64dd251b8647c59ad40d5cb3ec7bef mainnet-01108-42362545.era1 +76d159a9b7ba724d20b5a6de7947e8e5a48ce9fc8e8e05dcb80dfe032411d14f mainnet-01109-bc521cea.era1 +02a940756d49d9be6a45272ab800d67856817f6bc8a098b2d2ddaf7fefbe61c2 mainnet-01110-199eeafe.era1 +07661f820a67426b63d1f8c90c0e72301f64371337f6d04baad2fc548466fc14 mainnet-01111-d3446282.era1 +aa3d74f50754f2454d9fa4b7ce5830128a7e578bb3e3bf602410ff213079de88 mainnet-01112-1c93ba5b.era1 +c951c5d212149de8e017db8ce6a147100a2fbe907343d1fd75c6b85231004e77 mainnet-01113-beafcef8.era1 +693b9883a3b1b94f51dd9b1abead7b47a9caf1f50b7d5327678a0f55a79aff23 mainnet-01114-71ec790b.era1 +257d13b78b096ae907f2d8c37da31af8a0aaf2a6c55c6e4b651b3caeb48be7a1 mainnet-01115-6f6094bf.era1 +33e76f63eeefc3b82a6f651acc73c2514a5bf3139491cadfd9caf31fd6367120 mainnet-01116-053afb71.era1 +1052384909bdd8a400603abf7e0bfccb83952d1312b35a84bd8242ea8ee22c3c mainnet-01117-98396ff4.era1 +8f0c0ee760bdd5b34d1ee4f031b18511ee0bf397ca1cc138bac1ed9ffced9768 mainnet-01118-57479712.era1 +53647ada8269cd41e65fd17e59d90e0a7909d9cadce79abf28d7bb31cd754acc mainnet-01119-1554c473.era1 +492ea63b5092e9eba1525546a1bf2a6709cfe87c2a4eec8bedc8436c26745ad8 mainnet-01120-5db300fa.era1 +44ae269d3e8291e1fd98177bb419205a7bba05c2960ae3a773ed85e99bf0e7e5 mainnet-01121-b9aeb88a.era1 +5fd7882a18010543684a44d2246d4c35c7b676fcbc41bc8082341a9b7db42622 mainnet-01122-a8849157.era1 +4bacacad8b1f09c93144dc85414a483d4e6380d7655ad33345cb42287735c7a8 mainnet-01123-0b7bcf33.era1 +486948076131219d1ae8408cc6c6e13bbe707577cba8ba88d2e8a3b62aaacf12 mainnet-01124-224f4405.era1 +5df25de47e78d727b3493afe919f0c59371f8c58aa08e85bfd15240a0c6c48bc mainnet-01125-0b6064b3.era1 +0d478eda34abf9738783fc5e3c19759515454d20e9523a6d6b983d8576ff651f mainnet-01126-c7344cf2.era1 +61d872eaff6fc36378b47c78ef3301a9cdc4612e29b8f55f7627b65cfb3c99d0 mainnet-01127-ad12ba38.era1 +8d8dea3e3f3ef33921c2dd3f76bb1df1afe174915835d57a934762877259f675 mainnet-01128-3a386e6d.era1 +5a45d158d34d4b91f76bff6e0f224f7b3f713a3d64a0bb85e6ebc3ad06cee638 mainnet-01129-c77dcea6.era1 +a196a55b1a930962768945133597054e8ab8420c8b2347049726ce0e8638701e mainnet-01130-a25a8fc1.era1 +840364bb4c929197ad5a9d39a106d4900c7dc1c335bbd05b7b59df034208c67b mainnet-01131-0225209e.era1 +72d73c29f6df76128478453c2832e15c4f41294889a8f6f5414c2ca175ab6ec7 mainnet-01132-1ba9f77c.era1 +bf4159c5b85f495dc486553cdad3eb4f6ebc8423161ff01e7e1018c28d39f425 mainnet-01133-8e1c1d63.era1 +f22ac40f22a3e3bd8621d1d5ee974936063c95c4b3cae1e168dbf9fe654040f8 mainnet-01134-3197a1d6.era1 +a0bba5215642e11b803b79d74fdb99ab882f1faee1fd39cc5a9cb2dbe06796ab mainnet-01135-d28f2c9f.era1 +f9d70ccb72a014ffc73597a2ca0f64a2cdd7d0020a15349716a662cd42c40fcf mainnet-01136-6cf8d26d.era1 +7f07dba1ecb6618772d4800eb19165e6fbbc1b8375422250c4f13dedaf448ec2 mainnet-01137-62215680.era1 +87be3f04548dd4161a991e1a0093a666a072971d2514cfc367a5807bb32a03f6 mainnet-01138-44e4142c.era1 +c15b673920e6c2c56879b2cd87eeb9024851898011090c6dccecdac8516cf1c3 mainnet-01139-1a70666e.era1 +381abbba5cc8cf7c0b45a96fe730ce0406161cb825735c0cdc4231f78ea16008 mainnet-01140-9bef85d3.era1 +42f9a2999d097cc2148ea7f93c6a1c89a46cd2068f37ca2f15494fda2830d9eb mainnet-01141-48066cf2.era1 +bf8b07de2ec39c355da7b30e06e95e0f39c1f30f9f1d9f4c85a2495c2fb5fbe0 mainnet-01142-112745d1.era1 +8750348515c1d43ad51d0cfb245f15a7b637f970de34f6f763c81625f296d65a mainnet-01143-c07f5625.era1 +32f9ac799b52f528daed2780d8b79bc9acee50bcacea386a2f2f7d221050063c mainnet-01144-ff3489f3.era1 +af3e756ebc415d0bafdf3b082fd50d3abf37525dbb442ed5243e5f4b3ea08a15 mainnet-01145-aa9a507e.era1 +f1863c4de8ffee8ab1cf9ed366fda800276f407ada526a4c6e2a318bac60a93f mainnet-01146-ae05fa5d.era1 +21bd47773e374770c725b4809088c46ad97ac1f63e9c6cf9eefd23927686d65b mainnet-01147-0dca795f.era1 +4f95ed27a854b4dd9dfdc4bf607261e6c6916773f572f2e4b0de04d0c9df8b1f mainnet-01148-b970027b.era1 +1814c3b3773adc356d8b5aa16201d97c16865552d2338b66d5dd7ea42fa94fbe mainnet-01149-b2f6f517.era1 +06e7013d7e74c6a3bff223bb343160748c5cff8d23e4ec62196692940caae233 mainnet-01150-ae9dea31.era1 +04db87c8a1ddf007769a332ba44dd3d885d2fad4c7e35447493192cc4ec34f82 mainnet-01151-1cb2b8d4.era1 +8505c37ef3bff814772e094799ff748c9bf5befbdbfd5535a257ea9fb75c513e mainnet-01152-28b41e38.era1 +4b53ddd657e94ed3e798c36b681b2f81d1f532add195a5dbd1b5b2fe8597decf mainnet-01153-9cc1f6f0.era1 +2ede6bcdc623794d5ba9c13f2f8c65b3c6cc3bde0a6a1bdabf4102db4e25f7f3 mainnet-01154-1d470ae1.era1 +4fb4abc0c2727aea473e2d3216ae48525f8240423d18811f44b61dcc87716c6f mainnet-01155-b516307f.era1 +10c01bb633db2fde70660d215c7dd7d7e5708b1da1cedb1342b58b2f93fd4009 mainnet-01156-8c4c1119.era1 +fbede5bf3794645fcf6d9e6ef8180d9474658d8dd984cdfd58a4c4e5d81f5044 mainnet-01157-d7bb8fbd.era1 +6d1372e9f0213ad9a6a4d3096375e9681b9bbde4c424b778c278e6f737988e12 mainnet-01158-12ec0bec.era1 +81d2253bd67ae0a17b73541bd6d07bc96cc3059be380784bbf1e0fbd016544d3 mainnet-01159-4fafaf52.era1 +3606259ac7c812b03f91a002773d2b83f9d8dfc3f9011f6448ec0f5b8c25d725 mainnet-01160-d0e1b363.era1 +4ec53f617ae6e948775633026b11900ee53c363590f6052eb7623a100f037e48 mainnet-01161-caff5303.era1 +d0a093057a4a9d018ddaf3716fcefa29a9d76320456838bc7187b4f58e682b84 mainnet-01162-070dea60.era1 +016b9a8185d7aa34ea226975f8ccc37e168a863d0d21cf31d1d5912e9ea3cc55 mainnet-01163-d285b66e.era1 +b82af4019e231a7960f204262524921df9a9d249528f19face594c80b6311330 mainnet-01164-2eb4c50f.era1 +a4f27f235b35f59146c2e945abc1ea89c5e49df5702423c098138c4ff18bcd9f mainnet-01165-ff4e71c2.era1 +39c3973459e3dc04e5a9e3e363498ce1f5e67da950f7464faf5fb091022e7750 mainnet-01166-4116850a.era1 +cf6cd7d4d48a6a33b81a99a6f165848b8b8feafa3a123d79c5a5a6f1d8222e80 mainnet-01167-5b698645.era1 +c70360eab450f746e535e0cb8eb236af779ac4f17aa110ada2bf1ac65a0bfe52 mainnet-01168-a23912b4.era1 +d57c0d867db78864af6e6ad62d9022b7ccf48002172a1aa41bc112eba378ec96 mainnet-01169-0737b4e5.era1 +595775629d10dbf6dbfc752293ecbdabfdbf1c3184d40647b3c0ce5ba4364fec mainnet-01170-df35982e.era1 +475d800ecbeda476068354341f9e30efd0d3a9d2e4c2d1bbc3d2637460d6c958 mainnet-01171-cc7466dd.era1 +e170b5a5d077f5fa1071220a290e99d4ec0e6cd0f08c3f489cc7e3e8f5a5fc93 mainnet-01172-9abdb4ae.era1 +c7bcd71886900eeacb2cfa148731845d27ea730b76734bfe3912c3d804861915 mainnet-01173-cdbdfbc6.era1 +61e83598aa81b1ed90dbabe6ae4e065acda4a00bca83120c96f0487091c0a52b mainnet-01174-d79c75b8.era1 +6530e6d619c22c585b2d5278fbc722fa6d5c4e50db60b13de50f41cff7f80989 mainnet-01175-0d2dbfd7.era1 +4a06ded80069ad524f38a81f7ca340b28e424dd7441be0ce07658a7345740e3e mainnet-01176-94adbb4c.era1 +c2f256165eb05f8819c212499ba030f8cf8b350c3f37f756ff33f188106ba8ef mainnet-01177-d5e0dc5a.era1 +0c2fd41d9533fe0058a63fe235bf38fad34e904f683bb634fbca5cd8c9eb970f mainnet-01178-5c34962d.era1 +f4ea75ca9d75c6d4114c94d6ce904d6775e668775d17e84f6cde3cd3fe0fa8ea mainnet-01179-1de75523.era1 +9131b648784028a47f51ad723bfd375cfe5362bdbdb3338da8676edb008035d1 mainnet-01180-aac82868.era1 +7a487ba57da5bb3fea8ea01ee909d2a5498e5af9a80a887ae69a67209f4d2fb4 mainnet-01181-58996635.era1 +03deb922a1b8f3b5a6cd0ef5cff55a8a9c8b4ce3c9d77ea785e20f3cf0a1d43b mainnet-01182-74b8aa44.era1 +1cbf90260ba688290b8ebcebb54f325b5c6c2ca310491fe13ddff593c0f7bacb mainnet-01183-38d85671.era1 +0d29d24eee891361ad82df1862ae5b1a2eb2773d1c1879c0e01b2f2702169468 mainnet-01184-2a82d902.era1 +5a49dba599ff573884652f69cebdc81b5cab86982cded90b0b9092b412d9edad mainnet-01185-528d123a.era1 +4b0a6ebfb2a328cc7f6c7c3bebce5862f31387e8606bf9d728d07ad6158c026b mainnet-01186-dcefe6dd.era1 +6445c0340ead092dc5865fba846ad190950ab0ee68ce57a8655bb894ff5940df mainnet-01187-25b5519c.era1 +13977d383ba3945eeaf510ddc8aa731ec973e8ec208659c69b845db89478e4ce mainnet-01188-a8eec328.era1 +a24aff2c666efa07e0ec015b1b64a05041252b886a496295d849b49fd3cf29d4 mainnet-01189-09125340.era1 +c814651f4c00d1053e3810139062efa6203e323e06d859d9391d6c4ee6230f94 mainnet-01190-13085b0b.era1 +07f7ec8d3cdff76faff689a7ec5bda388df986a9742cf2da26e619964cadefa9 mainnet-01191-e8d4138f.era1 +345256471129f0b8bdfd544e6aa6bc7b4da7d8a5c9a0ec93ffdb1950d4455013 mainnet-01192-7a4ee217.era1 +a7ad1020b5aa38fa4ff4d291b31a0228e854dbdd3f1f115956ab463613602bf3 mainnet-01193-7c6dae3a.era1 +83ebac2b6337b01ccb71a1402e1839fc8d03b5adf952e7ef8d123c55c0376466 mainnet-01194-7d063ead.era1 +b828f0888a3c135d1af5e335e79f84928434fff164788f06bb489e2b738483eb mainnet-01195-68a0b792.era1 +59d92764901edf298f803a8b48cda4ea0b79e0b2df52e44b944f28b5d5ad7abb mainnet-01196-94c96976.era1 +9fc33c270dd919d77d97cff2fdd85aeccf3b52e9b13ff72a1a246b6aa605cfe1 mainnet-01197-a6c39440.era1 +4816e2a372f205e92d1b34b7be644441f6cd051d9e9ff9da33712eb69737eb4f mainnet-01198-f7a5ab53.era1 +47bc5ca9bb98735c1a97634dd5d02adcbde5945b3b5964fd673b5e9384b92659 mainnet-01199-84b9e12a.era1 +3b50781f290fa2ede67e95940889e44bcc370e85ca0c84d07964e92b311b8a54 mainnet-01200-a6b6a963.era1 +0de9940cdae7cb587d710cb901d0c07c823a9dd6219364d6f7918840ab055aff mainnet-01201-4a0c7f03.era1 +01481f0c79e7e0ea2af40b80d4b5a38f7726da1a868756f0d8a9422da84f732a mainnet-01202-5486c645.era1 +9e8947ebe59f2eae8147317f22626e6ef424c35050bb292c4f9b74d3f3861c27 mainnet-01203-08a5313b.era1 +13bb7f536ddd6d9f9f9fd21d684f2ad2118b0464c1f733ee22ad1dbcda66abed mainnet-01204-97510371.era1 +86790f4e75276ee19dd2ef21c8c9a95038bdb802f95336486756bb5799e173a6 mainnet-01205-7bbd5580.era1 +564fbc2ad3ca12d50b9d1d892ac91d701bc441540e41562329a10c14724d3df0 mainnet-01206-61e11a8c.era1 +41c7147e448add71a9b21c94d4bc1e49fdd6375cd04163d71361b0c0298be39e mainnet-01207-37459490.era1 +6f5772cbf97c2f3ed2cab5990242a8678f2bad69a7cae1a45224ee3ae5a8b5d6 mainnet-01208-4d0cc348.era1 +192ea288f03a1f59bf08d0e06ee519f72320192bef37f680b62d5d15a02e7f20 mainnet-01209-2008dcc1.era1 +5c5c25280dbc637ed83fac1e4295e06aa5bc462d403d7e3a3b38badc43463fec mainnet-01210-842d4195.era1 +a3281a2c120c19e73bbebda715847cc20caf2028bb9d647ea2089077c86c84a2 mainnet-01211-a9c13697.era1 +a6a026943d1ae7274de83838b877b47984f777b7df1f3013bac62ef560107ba8 mainnet-01212-a6435d49.era1 +e015c22e00634dae4505144d499554ad363523371a3e513d97658b8dafe15a4c mainnet-01213-71e5659c.era1 +240f1b91e57a77b5832fa055e91b67f5f97a42fc54764bc7ca488453423e2f61 mainnet-01214-1791e683.era1 +332dc15434f7af625143c6c3f5989addbad7f16d3b07538c06cd7d3703ce1fa5 mainnet-01215-b250520d.era1 +e80c9baca725dfa9959794b280d70b75b9f67d740b88f06ccf69184a24e9ffa9 mainnet-01216-a13eb7c2.era1 +6a2f77b4f9d7067ffa99d1f67025534f533b14a06327b63a4ee94eecfb57b6e8 mainnet-01217-5c83a392.era1 +c684f238f79e63b0deac70898a9f27576b1430517b3ae23b50ee25069592d1ad mainnet-01218-c13220ea.era1 +88d1d4adc93b5680856088abe8d31161fc8360188b3d040aca98d7e126751c46 mainnet-01219-5f56b030.era1 +d9e73a19eb37d4987a28e07079107e3cdf3018052b6a9bc348960f1eb7a5cfa2 mainnet-01220-512900cb.era1 +657c125ac26f2c42bf31158a411d908f2d2d73fdbcf628844583cdae9d62cb9d mainnet-01221-90c06f46.era1 +e4615ab4867d13f8c216508f6a4f99ec9e953d5fb352e06eb620c8dc38526fba mainnet-01222-096acd86.era1 +d8ea23ac75bdbf10b3e5cd9a695a6d112fd9fe4d129e1922d68de12238622266 mainnet-01223-1a1baa66.era1 +1c0ba11faba7076a9026e4b509a8d3e55f2dda54d7cca819e71c10d65420fc6b mainnet-01224-34f529a2.era1 +146ba8c0070f24c129c8e055bd1c45acfa87a4fa07d2aa0171f3f87b142d6e39 mainnet-01225-ad7198e0.era1 +9f04e9b228eaf0f6c843c109f93e13b3bb78a76efb6e21febfe2b74f3bf9390b mainnet-01226-2d858029.era1 +83210bd4c642258e31e29a69fffdd44dca7f81d6076b06fc6107ff3c577c7a8d mainnet-01227-bb9ed6f3.era1 +40da5526ff0164147c683769be2b053ea2b18a3e43e760bc7939a2b0b1dffb49 mainnet-01228-024d8b09.era1 +9d9ede24c506913cb27a328c56f60b5b8668f83b4c96f6f1851cdf4b4fec75b9 mainnet-01229-4fbd23d8.era1 +da688e247e00489555c25570cdfb9d6dce177456af52916974220ff0fbe3aa7b mainnet-01230-b70e3603.era1 +f41306c021272c4f2bb438f77ab3f2e2e734aac564d0de4890e96c9b435445b3 mainnet-01231-76e468cb.era1 +a056a64ab8bb0f5aff4c387c824e4bb321e9a791871179b7334c734875763a4a mainnet-01232-7cd7b651.era1 +787d4bd2d9a7732648d4a82a4742e1613c7ec44cd9b05279a3e436c391f598a3 mainnet-01233-d077ca78.era1 +276bd1a16a4caa8496fd6546afffbea6bf77b95fd27c4a4a93f774c0f9c8a620 mainnet-01234-ccf5a0f7.era1 +b876aa33ef886b8fda3e0b6c662e414379255ef4637910a1d2b382cc93bfa675 mainnet-01235-d7666847.era1 +e7306edbea916db1689f079213a57c7ac8d85862fd8f7bef3c5787a8f060fc04 mainnet-01236-3d10b175.era1 +78915d2267090010736974de75be869bdab6a1c6eba2db6fac98793511da43ec mainnet-01237-cfc709d6.era1 +1453318be63fa843b9093a8854d6637975c7c101fde14290fc48edbd45bdfdd0 mainnet-01238-f6f1e083.era1 +653839c244591ffdfe2c587bbb525bbea199dec20c2b76eae634d1498db2d642 mainnet-01239-cbeef9b0.era1 +7f02d914a1ac094137822197e7937690b94938297c3a5528611b7a7e31a1f000 mainnet-01240-02688fe8.era1 +e2e49c79ad5c755d8563f633231257c72df94c5d09024cbee3e11b2b7cf1afdd mainnet-01241-20ebd652.era1 +ff4ce149bb2465076266a0267034440bed5535c2074eeda82909684b472c579f mainnet-01242-ceb89cc1.era1 +35d472dc040cb1c04a39c68bbf638485bde139c63ba0dd89c04309801bc5276e mainnet-01243-6ca6a14a.era1 +f6d2f31e47435a9bda50eec2e5bc2a92abf11399f021e1eb90aa202560e35473 mainnet-01244-40769f6c.era1 +58f234bc312045351066024a1a438a4de4607371fdc9f721f994f1fef1efb76d mainnet-01245-f2f56ea6.era1 +e9e84173f9cb74d9ea02f965c0af1bd634e80a98cbf90ecc9b3ce62ac6e11ebf mainnet-01246-c0e897c0.era1 +c5c99e8a744476544b5ee1f63c1f884d9c11fd24fe47c2e8565215c5c09f77a9 mainnet-01247-58d2fe58.era1 +8995a517ecc43dd474ee81d84db7acade36d6edd2db327e086ac1789295a5f42 mainnet-01248-e2cdcc7c.era1 +0230977840319fa93322f591a7b920a54dd91dcaeed3ca4d724d4954313d6598 mainnet-01249-379da93b.era1 +36069d8fa590faf508b0b64684e967bea94ef01b22a87c0d7ffc1aed3be390dc mainnet-01250-afede008.era1 +cdc6b15be72dc4095678d8064eb2734c576c2880e546d301b0f90139a345056a mainnet-01251-eeede50f.era1 +9a170f1ddba4379c4e8e7e9a9ac8f32bfb2e43aa05c3e6399a18cf48c941f6f3 mainnet-01252-c5b81847.era1 +a49221586db21315e377b927628313f9dcce3ef9b2b644a0b38d5498a78af290 mainnet-01253-96748f67.era1 +4f5c59d345bbfe445f576c69e84b93f6039044dacd90be7dfabbfde6cf16e7cf mainnet-01254-5c3badc9.era1 +54e2236adc2317eeb9f8a8b658c6dc7c35cd945809a6f27d2bd63fca722c0170 mainnet-01255-2599ae05.era1 +2726f17aa58942e5b5c827b3c8b928c285e87f873487687525a30a5a1a111476 mainnet-01256-2b44aee4.era1 +723b298028bf04446ac6e05b2619130ddb65adf23f6f5829e27d6fc92273af79 mainnet-01257-4952c512.era1 +596689f86e347d0b40880a5d550ce7947b3d175b810f7082e54a48df86174bda mainnet-01258-713aba14.era1 +c0dd89598b20a411b933c13f08d7c6fb19a16029b74f99c95d089e4915bfd95d mainnet-01259-1ae7b5ef.era1 +0094c7609647801d3b73fc03c9b8dcfa2b8c7edcfbfcae359851714a7b87da4a mainnet-01260-6f90c321.era1 +e4022bc4e10f4f03ae45dece6074679a850dca4ecf4c4e26463163f8229812d6 mainnet-01261-61d416a8.era1 +50aec2a2f05df43c4b112afa8fac437d25b5cadeb45a53848e064fc1b9fa5579 mainnet-01262-aee21385.era1 +9a2e557765a00817c1ce2dc32e2187ea9c0e97d81284725e6d1cd639dcf63f99 mainnet-01263-9fa06b72.era1 +720e8ee102ac6a4efcd44555926085355c238752625dafee6afcf826f7e9b113 mainnet-01264-53a8cc3b.era1 +19a6fa6f6a05862416f0bbd72549f316e21921a8625d9e3f020b2d9dca6f2844 mainnet-01265-1366aabf.era1 +60ef14179f622a314e3e63abffb42ee6e4741aed4eb6983c8ef5868677f12f89 mainnet-01266-2631621e.era1 +1004d4829ac69cfebfcf177b73d7d3ed7248ac12b9713a6fb9db3946cfea9f5b mainnet-01267-3dd94158.era1 +1c772e74363742e058f003f19f65ef1ff87646defb9946e2bcea1f9c060adbf3 mainnet-01268-ed99cb91.era1 +d1cb3fb6577e706d164d668977f2c7f1ab4fb82d9a6dd192a14c309ccee89d4e mainnet-01269-3e65584f.era1 +bfeb65c5ec20f46232dcb9869fd6f3a016bacf4aa679b01cc5c0594f522f7177 mainnet-01270-69ccf142.era1 +96a1923cbf40ed50749fe02ab6ba42c8fa3dfd6eb9e1f0a94a35b70f9b78f6a0 mainnet-01271-66fbd4f1.era1 +59de1f5a8fba96663a39a5c2b1b8df45c8e86a6833ba4457d93a86cdca9abdb6 mainnet-01272-7f448c5e.era1 +988b890503c163ee6ffd22acb6c5576cf4f6614f8f55f4db55ecfad02947f36e mainnet-01273-3db6b5ee.era1 +cc04d78356f4762e7753cbf6fee1f5372486feeabf83b5e71b1761626262a30b mainnet-01274-63adf378.era1 +10354faf8a0bc80af4ecff9d5300ae12aad11f44dffe0d03faa1aba62c2376fc mainnet-01275-0c89bb3e.era1 +90fc0dae0ef111e66c11355fde4394e575f54ccf114ac328339877393701165c mainnet-01276-399bff64.era1 +a85a26858ca53bfadbf0ce9e3e3f6d9cf0339d4776b1426594ebb9a59ec031c5 mainnet-01277-1b14df37.era1 +6cc09625423c09edd772c178537799b9574d71548dbea2d979e7072992e1e1de mainnet-01278-7bb5b295.era1 +39368cfc2ced10c4e0abe27cdea8351111d17948a3fe560a7cd866286facfe29 mainnet-01279-4ba003f3.era1 +38ddddc4c9ec93c6f4357d8dbc1033d16efc0c2bddf56f7ade6c474163d56572 mainnet-01280-2ab6865f.era1 +dbc86ae92832c804bd6c9bc6cd2023a4577a7fb2ae5e5965173ed0b67b2e7c49 mainnet-01281-a5598247.era1 +16412dc3d507e2f5c978903f485fa3cabdc393406c3ac256441178242b11e45a mainnet-01282-8357bfd9.era1 +af6e6c5a9064469827ecdc95afc44b765a5f0711fa90d422e021ef12e760f7fe mainnet-01283-b502eea2.era1 +42c1ddacf27e325b14e8cbac5620fee7b90c0394a7e218365d4d899184f0b410 mainnet-01284-f9cc2497.era1 +c4ee83b0840b9e1491699b6b4f4405c020401d9a810c5380559c2108eb9b0c0d mainnet-01285-5ad4fdc8.era1 +6e30672f57f37ac89737f32765fed41b2fec36249b32ad7dc97eec4bfa7fd71c mainnet-01286-4de64a70.era1 +4a454402f31522bef8aa28fe8852ecc3307dd3d918fcb67d19dddbce3885c87e mainnet-01287-1cd8e301.era1 +c25655e481cdc4fc991b299ae067a6909c359d62dea887f1cf35e954f6971ad4 mainnet-01288-461721aa.era1 +58163222d18ed04c31db06ee1e77e60a83c5461459113ae29f0b961608df2337 mainnet-01289-d776cb85.era1 +7e28f52f1c043b809b58d97dfb880206494fb0075723e44c27c021a94fa6b7b2 mainnet-01290-873eb969.era1 +017542bedfb0b360f109d76bb52ffabfcd19eb20ec45498c57f869254fd96efd mainnet-01291-3466a370.era1 +7029158d2d683f09729cee8e39314828ee0565277dc2757759c9cefa8f8de1ba mainnet-01292-f7c7ef3a.era1 +8b861921ae93420118284ab2a290c0dad9d500c6c7b81db7726f4174be0cf1c4 mainnet-01293-eab36fbd.era1 +09bf6ae22a2291d050a1a996c42f015abb24301150ff29429fc2ca5b59cfbec7 mainnet-01294-d38b96b7.era1 +f08965eeb9fdc69f3142876a0941078b2c7f9701cb389785651f5ba6d2425dda mainnet-01295-9a8e547a.era1 +3099ba185db6d2f9db70ef88b49344d867ded95a09234dc642797c73c07fc8f9 mainnet-01296-044263f3.era1 +8235ab9b1d14e907833ae85ad4de8822a40df73a7157476b35b24cd6bf266dcc mainnet-01297-2a6fa840.era1 +c83e6abc2c078e0fb54d55370366a23c06d7e9f4ecb66fb7c2deb663b68ae98e mainnet-01298-25e8cecf.era1 +e7968bca5bea8361d9777c057d0cff1f759a2df90cf1f42543363ecc1ff5718f mainnet-01299-4783a5b4.era1 +a8785b8a11f423ef761d28e7a3a8940b436675890437aabef419817407eb902b mainnet-01300-05128f56.era1 +9f0dde66478065a5173ce5bff435a39ed2dc1c30826cc1fea205f65ac79495e0 mainnet-01301-f8ad3107.era1 +a9d03ede167e577bfd7bca060df5cf72436b9a1ddea598e4fec170b221b83032 mainnet-01302-564f335c.era1 +280bb64da624126213fa779695c7ee32bfe187c2fa4a9e31c6af92949e1bb498 mainnet-01303-0dd93fff.era1 +3e1b58db61947c5a1b45ada5c9c64d9686ce421174dcbbab5c5a65134044f32f mainnet-01304-20eaa74f.era1 +4875455d7119b917fb82f49b255dd769169d66c8f5b7e40646820e0cc1cf1b84 mainnet-01305-d00fc022.era1 +b29fa8400d04e6b24f89a39b9b5e8c343d36f44d8308a739e786087edbb6ed03 mainnet-01306-1f67a41c.era1 +a060656d775c6284c53f1a36d79b1ca604e2e8bab852b3957fd43d3a0f605c21 mainnet-01307-2f77e7c8.era1 +81b2c72440a57f9d3b04ad238c9a7133de2f1efd020f62bc5fb9394eaada69ef mainnet-01308-8eaf029a.era1 +256a812c87b6737aa725ca16b854cc48bbee781c23e1d209c93fc270b1b6b1ef mainnet-01309-0e9134c9.era1 +920e4b3be271752b4fe53a3a07ff32d06caf07b1044c0dc817ff4962ddc080ee mainnet-01310-36d0712a.era1 +daf44c55b9ee3b0d0237ac386ffd61f8594842b00fe895f0e8074019a0a3eea9 mainnet-01311-b196f52d.era1 +81a4a2f671007b73025cad89c68330c3138ba0c547fe18af2aa3955b1a8feedd mainnet-01312-052a3539.era1 +e2c81f6dcb0ca87dfbdbc2752449a52b5cdc480851305d64ba155500fe47745b mainnet-01313-ed3d98e8.era1 +19094842e9d0e78c761dcc6661f6d1763e58964470451f2a2710ec93b00f699e mainnet-01314-6711d975.era1 +ace576a9c744c7c38f272e111c62da33b4fe65a8f5edc619a3388dc4711003fc mainnet-01315-c90257cc.era1 +7abfa2f8199e55bd438d77f5da0f5bad1127d8a74bc99a9050516a4f2c383dbe mainnet-01316-d23ae50b.era1 +18bfea667e282bae9f4f0e67221452492e49a8cd53e91115869091036c4b91b8 mainnet-01317-b2c5b1b5.era1 +f68104365e1e4abba936d17bc53868818601f152a441f6900177d2dc56b4014e mainnet-01318-803d224b.era1 +a2720d85bd277b218f7f68d7b1d53557d73479267f40da994c5d9135dadfd7b4 mainnet-01319-f7082c22.era1 +7a4c8f4df8f7bd62dade2adfa030ac0742e2a55d6da79ec4382a592d70b0547f mainnet-01320-66c7f004.era1 +ca7665fcac6d8f77db741b44e976596a0a0c785bf199df49df99553091f63ed0 mainnet-01321-04af06fa.era1 +7b31771617b1dc5b3284a0e2ab301fba9ec12b621dad9ccb5571bdb0375aa648 mainnet-01322-44c4c046.era1 +56fae2bc1641b01ce37537b761530da0ab4cb9dd8e166b805f32f199c4e75fd6 mainnet-01323-570d0caa.era1 +f638ff307a6390b3ff8dcbc49383567831ee5a9063f4ce8ef4033ac4e54ef585 mainnet-01324-d4cb7a0d.era1 +21ca9ba2766202aeceb4aa0ff0f4a3046d3901ed8f71786a34a39742ac1c4967 mainnet-01325-b10b22ec.era1 +2b26f4d078ff4f04d8b8eb96de5c024a3b97583d7e891623a8532663181de6f9 mainnet-01326-ea52129a.era1 +1bedace32560f94d1b02d419b4b5f190776c846110b5033dc31fb38230c397f6 mainnet-01327-4f88b085.era1 +0169f104bba10ebe1349fd82bca9bc54db392ea75c105550897e0a63da217cf5 mainnet-01328-83f1204e.era1 +91a7dde4a0edf5667fb04c6c78fe7d38ec2ebde946fb34e4951f39090b432012 mainnet-01329-572dcecf.era1 +331f8506237bb24cf7d3803452474285316dcc8ea98ef15bf4eef4cc6064b60e mainnet-01330-45db98fb.era1 +04f81f58920bbbf42ad4a2061cf59ebe30596f1fce26dbf6453d6d1bdcf51f84 mainnet-01331-79ac113e.era1 +1027d282aa646d5c8fa685e69a82474a46394d523a26dee346297971155e24fa mainnet-01332-2e02ff93.era1 +7120f994b83f2319c62825655b1cfeb828e30b71a5c700f6e15d823dfeb4d87b mainnet-01333-1c8da535.era1 +090fa69dd9c403e5f94eff043afae39a7e91b3b05071d7e2578cce777a2ab34f mainnet-01334-9983596d.era1 +358aa0ccd7de8410c5d056cf5b288f5842104804244d58d7008618d65c856382 mainnet-01335-4143f16c.era1 +071a5e58f4e5da61d3fdfec62e7eb78f9984c9e691d26a600cacb01ad33ca6e1 mainnet-01336-2c80acab.era1 +5f98ae78a7ed528bbdf91b91eb8300e4be58cf3e0b326b2ab0ef3b9f4288ca8b mainnet-01337-70afebf0.era1 +7251206639c8e37fc1e068c0fae077b0af83ef8d63b5bb2fa08602a145c92530 mainnet-01338-0d957f43.era1 +b9a2ca5ee55eb6dd44d249fb88097cb9e298448ec956dc22069d9a8e1ba3c725 mainnet-01339-a954d4bb.era1 +f5804a500f5c96fc3e628bf4d22743dc3ffd4524d57eef9cc3e11767044611ca mainnet-01340-d259e3db.era1 +4c2c2933f924dbbeb9a85ef9aeed72cf3129e7ac9c4c0649506baf653de670a2 mainnet-01341-a393c46b.era1 +f8b45dc8bc01486a5489e1efde75625201840dcf7fb89a340e81fa1b188a5ab4 mainnet-01342-febdbdcd.era1 +e42589d618af2b21dc4bb69d6f6b120cba058928db76b678974cdc36f21bd1a9 mainnet-01343-c205cffc.era1 +fa369dcce9af813ce9f731510589770e7238f09358c8efde7de2dc3f3176a904 mainnet-01344-e55d1bc5.era1 +a60e9d83f28290d2482f0fbd238e61735274bca66daaa6fa7a59349a489166d8 mainnet-01345-18129517.era1 +751c869193eeab784ee29ab2fdf4598371b9b569e3a31b4af797faa78d98faac mainnet-01346-62600923.era1 +62737b0cb00535cf635bc72b8fad4a1a775545f28415b424b2497d37761a5e10 mainnet-01347-b7bc048b.era1 +1356d26c5b96a9075a842ec37ba5d2a575c28531edf8fd2436780f2a85c6946b mainnet-01348-63f08fbe.era1 +e2783ba2d36fd2ffd8e04c2e347b9251a2772ec33f4bb985a3b56b745b1931cc mainnet-01349-d8f90a76.era1 +19bd461fb3bbf4beb58d475b988cc702624d69b490e5113b690837283589574f mainnet-01350-3b7ca4ef.era1 +d7544dff8e768f2cbd51ab40a3983d707d0ab2934ee29d1289b2eb56c38f50e4 mainnet-01351-a5aeba3b.era1 +01a87d40fc0deb2ec80255fa71092a4e18c76b98fab9eb864100b8474a4ccae0 mainnet-01352-75faba09.era1 +b976cd09d412c661c69d0b1f9b86d301fd2a1348ee8fece91233cee1e14bec26 mainnet-01353-53743d70.era1 +97ef2623262c43289dc1b097d55fbd1e36d0ffd5ec5b82315c1f73e2267eb400 mainnet-01354-dcc29cd5.era1 +29ce252a595b7ce7d16b3620b1078c65266eefb8d392a3869a20f53dc1ab063d mainnet-01355-73301488.era1 +d73ce56c6f635c1eab39a3c8a6471c30d242f44555be00633541d0deaa5301a3 mainnet-01356-c5358154.era1 +4b457254df3087505297c300b6d18d4623f77cae0e68d8bf08fce557abc35880 mainnet-01357-6ae35c6d.era1 +3f4c5e1c267f0f715a25e5bbc0c34eb1974371bf6441fd1d67068135f44dcd53 mainnet-01358-40401985.era1 +0bc31b98df3ca2c46c9f1e4672d6b00d03c5ded22afc569fb9a2ea13ad9636d4 mainnet-01359-4f6b2658.era1 +59a35576c168008295fa658fb87f4ec18aab0d8d46297d911238e6cbc81863c2 mainnet-01360-d0b1559c.era1 +ebb0970c37869805182bb0f8e41049ffcef7e003493e64664ecc61850079475c mainnet-01361-ef5b459d.era1 +f830f6c6695673742e55da926b1927df8ac3b57457971655c6fdc93b8779c9af mainnet-01362-08dfe9e3.era1 +5b1c0b75458116106ac511ea780fb0bdb441db0458b8d531645768d363050592 mainnet-01363-80f7dfd0.era1 +ce4738d883c80ce1874fe3755dc0ed784cefafd7c23009f2fb98f41a50e1e492 mainnet-01364-4b47710e.era1 +1b5a17c77982f23f514e1c6be2d88db5c0faa788fd87e774f4c5060e42148ced mainnet-01365-cc79e6c6.era1 +0fba63789d2fb5ea620767e7519783329f805cd16d1c358797a879fc6d81f640 mainnet-01366-d76553f6.era1 +133d860d3af93f94ac7fb78d709b16b39d50302978e7ab26a3f62c00cbe7dbf0 mainnet-01367-d7efc68f.era1 +a0b2820cbf08ace921eaa12a316be9ebd6adb81ce25b67ae3c4f9febe9862b1a mainnet-01368-17ea70af.era1 +53da9926f9aa968cf1d2c047ea37c7cdd922e650d01544f3c90401ac7775a91d mainnet-01369-f4a498df.era1 +b13022fb1a11ca7c6b0ea1e6e588092faa2593e57dfc5cf3f611ef45f61f4dcf mainnet-01370-027e2a2d.era1 +e9ddc8dcdd6b9082f522e2186571e929fb967d06473227f2c3bb69dec33f0a99 mainnet-01371-b90ef17e.era1 +49e5c55886a224573ae183904879fea6e59afdab572f78e4bd764ab8f1d12d65 mainnet-01372-b4719483.era1 +d8c7e3333558f050ba0594202e01e757fd8380626ff315e79f9c8ddb33e14202 mainnet-01373-b999269e.era1 +711aecf03b8bd204e770345c60ae0f3879e0a5077784a1da0c9ea4c12d65a3de mainnet-01374-662f1591.era1 +bca1ff381f460cd89fb9fa87c0f015c97a1eb22ca36158587ed4e96a96776abd mainnet-01375-108ccbef.era1 +5b5e841c9e725a1027a6c8938982f37a2604cdc308a8b77a9f24f1467b1f8fff mainnet-01376-54d29629.era1 +6cd2cc7e83c3ca0d08bf49a40f0161da41af1d6d68f341be4373a19b2abafa32 mainnet-01377-6d7bcae5.era1 +7786fd64d694cdeb834964cc70b7595d7c76ed236c8e0e72593169843d2a5188 mainnet-01378-fd477f0b.era1 +5e6428929b7cb5aa3eff3c4e0249306957382e9e304734c7ecada18dfbf2f509 mainnet-01379-57b72b9a.era1 +43addf5c34b75fe9482f8328072645bc17ef9aea096ee4f7c8b8512ce0f40228 mainnet-01380-beacd779.era1 +8900a0de91e023699743f61ce33457c05098974403b10fba0efb7a2ef004770d mainnet-01381-4b6c0027.era1 +46b507c7a377844c294d2232275f05e5a59c6d0fde73d1c00fcf11e32299bf64 mainnet-01382-485b0ed3.era1 +b1e23b51dba1636103604950c469b01028f6e641c3c5cba3a62c8f6d745e09d5 mainnet-01383-402cc664.era1 +064ee6442baf410bb426782b90948d3fd0582906c475d3729040b1dbd7ae143f mainnet-01384-547da0f4.era1 +4899fcc76e8069936a49bd0707a11ec90ecae225e238f42a8bf611b9f6604de7 mainnet-01385-058c55b0.era1 +3ed4deff02898719e040db928881e6f21edca03304f0b615e9174d27e2af5c3e mainnet-01386-951ddf6c.era1 +c6022db6e9081c7c30f451b3266e2aa639d22f95635109c31b073d500ee056b7 mainnet-01387-85a7797d.era1 +30030a87c2356bfb803d8a6638af8946bebf986b5a421833a019bf83cff0069a mainnet-01388-64376e67.era1 +b9eae82bd40f8701ac7970f24fd84333d41f960b7b0f7ea7de66ac56050bc41e mainnet-01389-58445b6b.era1 +43a3608276f808e23937ce0121922459293a605d989850496c11ee138b9fa988 mainnet-01390-6a2d6ce4.era1 +3862c2b6a685a4296890825c26ff10f133ae8b2a0ba526923780f2fbfd0921cc mainnet-01391-330e88ac.era1 +153b03e32abb8cac2acf2cb8596fd0d7bae740c7ee7984bbf705648008492ace mainnet-01392-3bf42cf0.era1 +151e349aa5c132e943c9c61f0d8dcdf470332968b1ac8f64b813f4f48ee1f23e mainnet-01393-239fa3d0.era1 +f0e0d1ff10a5c4538b3e480234b397dcfb5ad2ace98003135b3f400f672c03c8 mainnet-01394-76707dbf.era1 +e8ae97e74835238f588fea6ac5ddd546f0aa27ad4a62855690005a4da464f975 mainnet-01395-4bcaea6c.era1 +c8c7fbff86d136da6763cf2b990f54f4ad8c9f0e37a6c730dac52ff7e7bdec5f mainnet-01396-cc5b5c9a.era1 +59ee08c1ff222371627faaba48a1fcc6eb78dff5747b93908265ce86769226f9 mainnet-01397-ce3fa54e.era1 +24f8b067471cea0bd15e36bff586b4ae5715c0dc77275886a1da2d3ca28a303b mainnet-01398-d06c9a04.era1 +2971dfd0ab5cfc0585a4c75803637377efc89aa9279877b74dd97408b5f609a6 mainnet-01399-e131599e.era1 +e039e2e9f725c32a61574919b26232839a73a7844b44ae60a7c8963214f03354 mainnet-01400-1a628757.era1 +550c715ab4f6128d0f5fa9ffe1c2eb779c3c8e6c70562a66c80218da9698310f mainnet-01401-e7d4a880.era1 +68288f605024621e3e14cf90ec1610c42cbbce0b69c6af67ae2bd7358c3471ba mainnet-01402-85d3f303.era1 +4bf2e03672a4dbee47b8f5af34d296a30026320c9c4c23947e0ffe8435888219 mainnet-01403-e1e41aa6.era1 +26a0d4a885854d083fcd9e37adefa805bea73412145dfd3df665baf96a3200b5 mainnet-01404-eba27a23.era1 +c0b5759280ebafb0e867da46e4d5bbf5db7a8d6063b54dd6a0e1bfeb7743c676 mainnet-01405-b0ddf49d.era1 +23253a01baddd96f8dbdfffe9d1e078426b4677d3d12e5c2e7d5cd004ea60faa mainnet-01406-651ac24a.era1 +f8579d34d6bbe198a7a8827883b216f49b1342dedca2598fdf6476d868d282e6 mainnet-01407-a76ac2e0.era1 +50ad5742fac9ceaba1c8f4b470b4abfc7822d7ac2a33de684ef6914f748c9ee0 mainnet-01408-209624ba.era1 +e11fd2f4b0ceabb5b87c78bb98c1648e89af91a4e874e5f87c1b1ca3eac4e262 mainnet-01409-af729a25.era1 +cdda1247b3e40b95c52348edd0dc7adf00295c49e5e690abd7b5ef6974280529 mainnet-01410-a53b25ca.era1 +ec46ec3277de6aec68923500bdcf2ece80317e51bd8fe23062c60b9a93e5f364 mainnet-01411-00cba9ae.era1 +cb214c5b3d56da00ff519257e9b9c3753d2cb3293b8d3e8f727b74f1d4912ddb mainnet-01412-da3d50bf.era1 +94cbf93ced0fc4aa95ef7bb9cdbd9e22771e876e630e6fde313851559eed8f60 mainnet-01413-fe77f727.era1 +47d326864b404343670f3d4017c74fdb808218909f9c5fe5298668e1cdd403b8 mainnet-01414-1053d23c.era1 +2bdb9cef6e02b7435c7cdafd0f39973d45b3e36df274209287eb311d291947bf mainnet-01415-1f9ee408.era1 +449271b516378b806099799baa60f6f6d18994f2b2f228e4a2895691ff244855 mainnet-01416-162769df.era1 +d5e996beb771a4bf530244ca6d7cbf3e56f08ac58c5a359cab963c66e26514c1 mainnet-01417-6904f505.era1 +7886d7c1e992bce0026ca17feea1bd2e4ba79a044c4ae90c04565a82a1825e60 mainnet-01418-66837954.era1 +b39df5fdcfbf4b5dc24eb93b64b9842405bd341a2a24a3144859874812918e1c mainnet-01419-55bb8c9a.era1 +54f228ff43b89b77285bc0e0b5455db5f827f54a19cab17fe1ec8ed10578be71 mainnet-01420-37cb2c92.era1 +c649dfcd02b17c2db486d4b615d85bb21c1166a18d1c33d305c356c15f763c63 mainnet-01421-05b6cf1b.era1 +fcc2ebd17639a49670c82e7a54da022a48245d63f8044d088facb416d79d49d7 mainnet-01422-cf249616.era1 +2620809bbec0a5182223dd203fd74b1dce08122eb8c616cc4ce9443560b63657 mainnet-01423-8500cec0.era1 +0f95398ea8a61b7d617990214131cce800ac947722bed77fbb28bc8f3e482a09 mainnet-01424-f9b23ca9.era1 +4635f7300b5365a9ff84e6277235b580d679464518869c52fe0c071eb201534a mainnet-01425-2e9e77d2.era1 +fe37f157d5aa804adca28571f2071703a2498b6f5fd80486391ccecd0d0e908b mainnet-01426-8c071005.era1 +663f0ed02b6b32aadb3c2a703e62ae0d2f878207f6b41a95f86cc7a467279f9f mainnet-01427-53b8caf6.era1 +5248d97d29eb6998b52c2a1cefab09b16c7c031f673176c570b62341653ae031 mainnet-01428-68be6c9f.era1 +7811c5e4bc35527005852c8435520d59cd902cd41eee2e0cbda7d4f049cf11af mainnet-01429-12a34f39.era1 +1ec5eda1110cfaeec844abc4794042836c8b4dfe9c16ef0a79f6c7342f76d062 mainnet-01430-ff0a7be9.era1 +1ac28630745631a76edfcdb5f2e09fc1c089577c427e28a743db0335f5e48eb1 mainnet-01431-64d4fc5b.era1 +06087f72cea1fd49e3aafa8033adfc4e098ee49bc20642a474c85081c8a70ef7 mainnet-01432-2205cdfc.era1 +8a0fc7e9fc2ef3b49590c1a17f93b7795d13dfe863f609e4ad6ea997b1f0b785 mainnet-01433-e4ccf743.era1 +d58b8c466c548174751d212b73e15a8455adee4f71644080acba1155461bb046 mainnet-01434-77202058.era1 +e3945c73830db6b9a6f7b5fcd17ac292131a9838bca96df6f7e5cb8d173e1c82 mainnet-01435-467addf0.era1 +b6eea12a891a32bb6e8cae0be78406cd260bcb13148ee22ec498d359e9284036 mainnet-01436-8bd916a8.era1 +258708f393377fec046013eb172c2667c6707b9b647698c65d7eb44737c56617 mainnet-01437-332b343d.era1 +0f3939607d194332c2eb9e653b430bbc86e0e2befb2a9e14eeb1e161b32f1374 mainnet-01438-595d9cbe.era1 +7bd68818b8ccad9090066f14dc52845be8668f19ea461d35d850154a18774e41 mainnet-01439-aed3cc6a.era1 +30ea77ccdc53fd2b7034000a4f4741ce53d3580f9625db147a6a63ed42ae2c55 mainnet-01440-41f0520f.era1 +4f7eb2c90307cfac84978570170284598db309420e89e9846d28dd22f6671383 mainnet-01441-e2a38fbc.era1 +72040094c53ccc955ea8e57cf5af40413d1c07e24f8d9aa17a933fe31a39869a mainnet-01442-ef37dd9b.era1 +23acd9d6182cee70eaf6ca004b371827712a13f4110f71ffec7b71e117ba812b mainnet-01443-145a661e.era1 +f020fc7faa8f6dfc515f738dd978dfd6ae9115a65622a861c3ce22c7ec14585b mainnet-01444-9821beb8.era1 +d39a4606cfce240af8de5edd4949ce9687fe7bb2c1111a1121df44f8a5a67cd6 mainnet-01445-728597bd.era1 +d1285ce2512ddb1689343ca9d261047c75b789068b574769b353726deac9cbcf mainnet-01446-5ad80991.era1 +e2a7cffb91e452a16be34901d97aecbaaab166ab10deffe5643bc7063e94472d mainnet-01447-6b884cac.era1 +947fc8b6c496bfe9295cb43245a33d669171433e03d8c99e5eacdaf8c66a9cb3 mainnet-01448-869cb3c7.era1 +c0de9d0a34ac81edd5dd2fad777baa87a0f02631c4d5d9c67893bb2dece5bc66 mainnet-01449-5cac1bcb.era1 +9e94a360b729c2b7f5528cff27e651e0210c85e6c15e2ce329f2b97d5c938f74 mainnet-01450-b9278411.era1 +0b46c80caca37c2f6e81c71fe22bf7e8dcd7eb9820945170c4db1cc604642a29 mainnet-01451-32f5e0e5.era1 +029949a8d6a72ad330a3ef4de2a0fa0f9dcd19fa0ef9acd77567a76f0e66d4cd mainnet-01452-b43138d2.era1 +655e1d40f4460af26df21fbf85fd19f369d6ceaa04b94b662dbc99647179ec72 mainnet-01453-34bcded8.era1 +c0d73fb7410233d63eb9530dfd029d37b626b96dcae5ee67d53005613c2cd162 mainnet-01454-11f80fd3.era1 +3c7acdc8951c4da16a59c3413ddc92242e7939f4c694e7afdf392e610d42622d mainnet-01455-18ea77d0.era1 +8a0daf91f9c12c1d42d974d081e192dffcb4c69bb392041e2733d96f0c482d52 mainnet-01456-f1aadb7c.era1 +f4c13615dba720a8f75fdf351a3f508bd976c4ae83d67adb3cc1d2af8ec9c152 mainnet-01457-d00e9e6f.era1 +875f458bc26979c34e221a0e9f4c6d9951a69081e88a1a6658466ab490b179fc mainnet-01458-7ffab11d.era1 +e48729e17d5606eff2088dfe1f918d780fed77f54cff97d00373e6ecf9cc1027 mainnet-01459-6039b280.era1 +1a272e704e29a3a720c8d494b4e85429e8ad8efba1e86d03d244e42c305d607a mainnet-01460-8e889e14.era1 +57219d1e9b7331b75cdb5680b4a220cb29250d3a946036bd1760e488bd503c56 mainnet-01461-773c0e11.era1 +d644c1708407495e82dd2007d3daed7893c5436c8163b8d7ea12ddb11c626882 mainnet-01462-df1babfe.era1 +328526d39e8a4827a45ec6f6aa3207f20c75d4a8f234b3479ddc53507ee973c2 mainnet-01463-6d328022.era1 +0d763982c38b56ad61733141aad9fe28219639d3afc1b4add07419f8fefdbdd0 mainnet-01464-1c7eb43c.era1 +bddecd820bdd0408dc8e89728fded6317386494ce38b163846f2e69d5388e9f1 mainnet-01465-10ffef9e.era1 +d9595c500b8d4b83015030e238e9accca337b461b8ea05a4ebae657dbc4b2847 mainnet-01466-7785bbd4.era1 +c3a1ffeeb26017bcbc60c02e78490ae606d464f96c1415e42c65a59d5388e823 mainnet-01467-b09a9b8e.era1 +7f1fef22110077eaf5299fbe2b68dd2bc8e32283ec71baf34166f8472e9a87c9 mainnet-01468-1919baf8.era1 +8294a9de1df2f713da58ad385fe5f998bb7f357cc474132515551fd07884ac37 mainnet-01469-6338bf7f.era1 +4b74fb9a3a8edd99ac5635c148618a0852c669f63df0c99659ec95ff3b88e82f mainnet-01470-46fb7a9b.era1 +24f0d5f8cbaff1b381ff0c856ab75bf59e8aa56d374e5848fb95ba6fde700f24 mainnet-01471-18fb7c8f.era1 +b7818f256e53486839ba6d6768f0600079597b9f20522265192ac8030c745e49 mainnet-01472-47a32b9d.era1 +7b1cf4d233aa7ea6fa0d870d1a7e1ab30670ed65a145acfa1f1b80969a749df8 mainnet-01473-333b7e86.era1 +8cd04cb58abc7da45f99e366b10bb73ccb7dbbdff63e9707a49cb7f537875c2e mainnet-01474-fe24e3c1.era1 +cebec68718bfb963d022aac9913c3b8dc753bd91c89c922e6175091bea150f58 mainnet-01475-81c78370.era1 +0ad4e0b20d58b882e9d6aa2c7b175ae71b68a378f8fb2db7ae5ce757d47067eb mainnet-01476-857187a1.era1 +16edcbdd31ef409559db026df862893ec3d55def3f6fe3b89df08f11ad198fa4 mainnet-01477-ad00e0b4.era1 +219f03a7b1d6b28beae01894b62223d9b14a31b5170e160911bc198d2fee19f7 mainnet-01478-8994eaa1.era1 +11e4ecdc331d0682687fb25c9b0074509721401a1b3805d7e4277c5b9735002a mainnet-01479-cf4abf0e.era1 +1004791f7fd598673fb3f1de73099581696dee5d58df7e3ff3f92735085f44c0 mainnet-01480-ae5f5367.era1 +aaf7a7f356371cedd630168afa7b5c5c66ea4b0f8f4f30b9f8f770d0be2cf5bd mainnet-01481-a121c10e.era1 +4359f1ae454034430f427926f775c92837066e8b816b8e77b48e315e5d3859cd mainnet-01482-2110d171.era1 +d85dabca73e870a41464dfb9d0d621e9302c7169d397b0d266291af6ad74c007 mainnet-01483-56ec2844.era1 +44ea248447182e4fcd1e02ea0029a9eb29271d4e4be6963113994ff772d4206d mainnet-01484-ba8ad4f1.era1 +159518bed983ac81d742d28e0d9c36aec9da2609bb7831a3ad3b692ac7045835 mainnet-01485-c56c3ef6.era1 +96e628e5f4548dcf3d691be556d909893a786d4e743d0c3a7b6fae6e536f113a mainnet-01486-57bc4104.era1 +631a3635b6102e3025d7a81a4f3d203a5e47907e37aba13ea8127123c7b30c55 mainnet-01487-122d8e0f.era1 +5f08d89cf44c555c7ae594a113688e8ef660982db091988e223d86e46837b324 mainnet-01488-42b25fd3.era1 +e9ba8cce1fec966b0237eac6d47873cf198b0bfcd9426ee4484c3dac7fd94d5e mainnet-01489-b1acea4e.era1 +a232396cc9d4986fd24e55121f721c85d3c7138853c32c63687b90ae37804951 mainnet-01490-34280f11.era1 +4fbb2af1cc0bc00e2dd5140da8b178431bf2c6144a54dedb045f98517b2e61dc mainnet-01491-503bfdfd.era1 +b31814c8d0016b4655779c448cab692824246c916b3c7940bcb5e31f64644ae6 mainnet-01492-1b74997d.era1 +1cb371fa71fc71d0a4a33c17c3d200d8b575601b9cb02a66353091109bd22e66 mainnet-01493-edfb26fb.era1 +189a4097e29f4e1cace72fcb032b6e89ed1601fc56c57a22fb54f072a93f0d20 mainnet-01494-da405d13.era1 +da0d7984339278660e96c34e34f747574c6ad88f06711b2124c778ae809a17aa mainnet-01495-3efe0cda.era1 +ee1b345b735da46f9d6f5d3dc3bd5a29ac626fe846ff013d940ed3835a619217 mainnet-01496-809b00b0.era1 +4d95a40cc150dd87d65db07f2226b41a258709d1afe44ced5a3b8661e2406d66 mainnet-01497-c6923521.era1 +eaa06eef1c79a08df66c3c880c944b8d4b73764d105545ee657d2011cbc48571 mainnet-01498-2ef9dbc9.era1 +0db058c7e692dee965d6c89c3ad3ec2289e157bc7f21e0a48631c13e616169c0 mainnet-01499-23a65ef9.era1 +737b67182d604632e495d3419afb72551b56cd2b6efedaefab26106258013ee8 mainnet-01500-17e97c49.era1 +3402ec4cb8df4a0e73da4105fad3765b8a581eb93fb0099f326cd363dc877e47 mainnet-01501-38815f39.era1 +1dbddc6f53480075be9e42447712038bd58ef70c87535f1d54fe2c0b5554f2d1 mainnet-01502-c31ef6bf.era1 +a27a320d801023f199b6151e982305d28bd09b339a11c1c88bfeebe9da0ffd7e mainnet-01503-c5393ba2.era1 +c7d1660bb9b1970884ec8fd0bc889bf7ef2c164962813c524136126e82933e83 mainnet-01504-b478f53b.era1 +d2ad6311cbdf2dd49bc6e407790547a53d918229ceec26fb9d6b72e8e51e3eb1 mainnet-01505-b8013f87.era1 +2a3b61fd2b53680cf3411a8436c1c81c2edc790b9f314b847c13ad0925f8c331 mainnet-01506-f23ee995.era1 +dab1a1ece8dc43fb51c020ea4043f07bdc3eefd049de662b4845c8632d1a8bfd mainnet-01507-21b534cf.era1 +5954cdecc5f4781057bd6d0d979ca9433fb6829dce045aaa1425da4bd3299d91 mainnet-01508-9fbff7e7.era1 +05d9c685cef8f8d2f140023521426a6405db9d954df79285f15065e96ceda595 mainnet-01509-e5141a21.era1 +f44d5da91e8975ac61a11091f7c1f4df06062bba7bc921e26740c4ffffc5da4d mainnet-01510-87aec91b.era1 +e9f8f6b2f4c433f171c843d7f877547f5e2eae6595e3831c3fa8cd7db25c3a2a mainnet-01511-b041bb19.era1 +2141bfc440a25c3709c21bbec11af208605fc6acbea3758b85ee8558933f4c35 mainnet-01512-e41b5ac2.era1 +66d286405e536c2cc59f5cecb90e963aabd69142247234e54fa8cdb5850b9448 mainnet-01513-56a66926.era1 +155660bd87dba182ebcd1bf5c60d3472063e9db7d26a586595e9ab6006f8bfc1 mainnet-01514-898d4f37.era1 +0cfa6d8521e4895b371e130b2f44004901585592d8c2365ea872c2cd979763c2 mainnet-01515-935b5d7a.era1 +491efbee84d36f57e582e39895f98d9e774051d8decf6d0ca165260702cd282e mainnet-01516-4ad5c3e3.era1 +cc6ca31096fc3ef2574e85b786f3db1f681b4707ecd5be234a1d7dd85bb6e257 mainnet-01517-be94d5d0.era1 +4882f5168a45010401d472f7742e91a5c0e9057cb1de13aa1673711bf4027e36 mainnet-01518-40fa62d3.era1 +71933f720ac13c6dfa662eb622549110d94a84881834d0eec8cf58d33ac4efc5 mainnet-01519-110e8af3.era1 +ab1b918ba41b10c0fb7b2ac74a7e0016c4a1013a9ceca3aa6e7872f4800ecc25 mainnet-01520-6e412e20.era1 +f3ea5d0379e73f0cb04f0525751dea63547e952863f9321375c7e5a985b9c35c mainnet-01521-8ffe28ad.era1 +dbe4c506e0acf2a76a28ad5a04967d6336b3d58ddfdaff5f714445e0220b693a mainnet-01522-e93cd0a0.era1 +185d042fb5e6b4c86cb2108ad197e1cb179c896a6c593bf476da4de1bcbe1a74 mainnet-01523-77f19add.era1 +73aafe37a41815c3accbe83ae518d302339c3a6ba9e8a8c2283a53eeb2068879 mainnet-01524-f583c727.era1 +6d7423924d47b47aef930b909b1f9f08730f47f2d7210be165a144c1165859cb mainnet-01525-326bed46.era1 +06e4b72e68ad8f8471827d1b5622b7aa5eb96b507c23a4160496e1f8e1cdd203 mainnet-01526-558f5bae.era1 +4305fcf21693115296a43a96f9bb46dc59fa89911147d1f711e4b64e8bd16aa6 mainnet-01527-17af0f4e.era1 +2a31614752754ae8046ddc39451171b291adbd0b5d9f7e8f5276dd5943129206 mainnet-01528-b3d28e9b.era1 +991bf22dab16b2108ad2b449102520b64c5580f23e2554f35da579a8e756ad6a mainnet-01529-6ce3df5c.era1 +6273cc58c1618d4dfcc71767a2ff4d17731a8eaa7fd64dcd7b285b30aea2422b mainnet-01530-70b295e4.era1 +b61fa4992aaa5215fea67d4b81f9f71ae273ebacbd98dc051d82775e834572d6 mainnet-01531-5694754d.era1 +3aeadb98bea934112453d371028a815ad5720782b834e15f7a551b8e29188975 mainnet-01532-b7d62fb8.era1 +89c0868bea5d3c6d08b3040af4bcc913020fe3209f578e0f0bd6cfd59c6c5828 mainnet-01533-1c4ea22b.era1 +84447512ea413fe1aa379f54b0e626668ce35d66641d6011fac103cfbc2d2982 mainnet-01534-3f50bd7f.era1 +18d5bc1bddf4f4f2cc36750a1fabda5bd5d101e55ec599e8e7fc819100e2d8f7 mainnet-01535-56e96bf3.era1 +d967e1886bb929afd0895eabea57fe8466cd91a38627a9610c9462c2f118cc54 mainnet-01536-4c0b5a25.era1 +dd6f936d078566b520cc8cf96b05a93f971270ac653b2dfe72fb6fa44029f8b1 mainnet-01537-b84376f6.era1 +52181bcf117efe1a469a9918c2b83212dff8bb394c413161a6e5f768d28ac54a mainnet-01538-a859e797.era1 +77aaa8c1d10420f6e6978fa46d00a727290439d7d7020a31f85a9523a3bdc8d3 mainnet-01539-b8f73328.era1 +fff50cc1d5230d7193097a94b57f6cb616dbe1c1c5d519a7cca6c10cc8972543 mainnet-01540-5075b4c4.era1 +6ecc4dd87a259c2621f7d3f7e4bd23d64c7b5333555634d0fa2f9e7797089ece mainnet-01541-d9a68897.era1 +3de40d9e684347861180fb1f164cc58fb42481a365f80062f24decbd3ab32cac mainnet-01542-4c44c323.era1 +5fcdd91fff82c163ed7cdc09302e77201c64b6bedf9d15a3957dcdade56e1a08 mainnet-01543-ba0d8406.era1 +a01e414694eef9f1f2984e7ae2c32d11d31900e39ad48db494fd63860c96cff8 mainnet-01544-b730d9fb.era1 +bef24f31d20a90421c90e8523a643c051141807306342c6e67303f6cbb03f4fa mainnet-01545-2a36dd0a.era1 +93ef8d3faffa706ea8dfc12345a2c7b1ace54c91d41ddaf039815cf1f428a40c mainnet-01546-cb6390d2.era1 +bb7cccfe47eb34649f0593e3dda7f82916661cc2262d119a1a7a21f3d860762d mainnet-01547-7be29447.era1 +63ff4c203e7bbf73f44d58fee4d9f05c4c1b890dd799fa27ec398b07da574e62 mainnet-01548-d42b2e59.era1 +39e8e2ba83464387f5997a9e46188defada3d96dc957c0e93d525a1c20e95c54 mainnet-01549-3259acc6.era1 +4bbcc6756e221e0c2206ae5c858da6f731b50c7717cfb2c73eae57ad4fe0915f mainnet-01550-15c4efe6.era1 +b3a8f035e443ff1e42baeecaa9af0df015a6c9b2ba9329384c6694b3186aa358 mainnet-01551-2d99a1dc.era1 +010d875ab6d7f9ad167aa7552c6d2a36a692cbceb7f8a1ee141828277dd0e2a4 mainnet-01552-ccd34c1e.era1 +908e58301e84862a7606650611347559345c9b0941b53de0e117267e3a28ff1f mainnet-01553-0f3371da.era1 +5d82854cd46149806494fd65362a6546adda300639525e5fccfb86c5a8b4668f mainnet-01554-6acbe79c.era1 +d0248d1e7cbc9a9d1a2118a45928b1979e191a91b391be76160cc962c976ed39 mainnet-01555-975db585.era1 +8a6a1d1e844167fe7579ddb3767db47f330d35259f2bc041a553a62000ae9609 mainnet-01556-f8d968d9.era1 +6293f17d2943184a9c6c44390bb65fc800212a2cca1de7ca320745955c0ebca4 mainnet-01557-5250d82f.era1 +55c059c3ee3e2284f89a1fb98a8cd4e657ce8ba60ce077c68410ffdd4b54e9a5 mainnet-01558-8817dc1d.era1 +3f873a8be5b8addbe307dc61ef53a110f2ce55a2530259c94e9a230d1f9e8815 mainnet-01559-16cbfdac.era1 +861b1d574ba05a80af960a65738802957208441616cfab1ca8b84828551cf5e6 mainnet-01560-cbaf55ad.era1 +cfa188c57de44897d2c9aeb8953692f89508b4e8486c0a5b9a775d345efcbfcb mainnet-01561-a12fc593.era1 +06afd26026b4031cc3e8de4e36b46c62573f851a38b9fb90436177a79d3f4427 mainnet-01562-310c6496.era1 +885a2881bde1a7c23629f2becccf2ceafc70d4b899db66ef1b8b8cee7f9491a7 mainnet-01563-5345e3d4.era1 +16c23370eced457e061e57abc676d0742b883c7fa31cbb9c3bfd6d4b20a4cce3 mainnet-01564-2280e4c1.era1 +787159001781cc1bd4633faa7b695d4ca247fcd53105ed63f5e6b0f9efd02e2c mainnet-01565-893942f1.era1 +c6d6439e53843b65f0f045af335e62ee9369a6c32e8bbcff4d1e40dbb4262357 mainnet-01566-237ef759.era1 +b91bd8aa86e20d442f88e8c08281413b1852231380639fd17012b385e8848abb mainnet-01567-1aec3b6e.era1 +aa96f4dcb3c01646352bab9f2b971a68eaf282d39a8c7ea31a11cfe434d4222f mainnet-01568-fc92fcf6.era1 +06e6119905bac7ee9daa9ed5916e0deb49c443afb55642fe1507c4d785d5cbb7 mainnet-01569-eacd9d2b.era1 +b879842b5db2608f1cedea127444ca7822082b76cefeee710501f9109c9ac78d mainnet-01570-a22bf288.era1 +18cb3d19703093a8ae31888c221b5569f92cd7c8813450cf5a12e83818114e68 mainnet-01571-1a439d07.era1 +e6c86e5e1360184283df511875918831368ec561c45b0f29aa04523ff6efc061 mainnet-01572-947ddced.era1 +9e346d0294064ba836d65ed33fb1c7b76d795754f2d7f08619c4d7f642e1ce03 mainnet-01573-3a831bed.era1 +b88fcfc397b8e40f1b5972027e0d4d06f8651fc73e5c71d70a5a62aac371b450 mainnet-01574-9028d18b.era1 +2252964fecedc20208c159243232d8a7d7057aaa330f748b9be887681468efdf mainnet-01575-598f030e.era1 +a20354aa4e90169203f04f32060da81e7d9e546ea4bb1eaf04a18a63a70ceb4b mainnet-01576-f9043297.era1 +42116706a2db87cdd04b52d956a4c47379f03233bf226c8d275eb45b1f5984e3 mainnet-01577-8a587dfc.era1 +bcabb605925eab14d7a9d8fc2a4b7cec4921a7f5d0533abaf129f8f4b8f86f75 mainnet-01578-43c1dcc3.era1 +2627f3b6b3007a17aabede2bfb9231d36e44e8eec38703e2f3ef7e7c984c4e0c mainnet-01579-92a983f2.era1 +0bf8f2d6b46e4418738db01923d56b76e250f53645bcfa0cf530bb68f3a9b635 mainnet-01580-1c243107.era1 +75bd2ec19aca5a74c590784cfe97922313edfeeedab25355ab285d3ee5ca70e5 mainnet-01581-1f943824.era1 +94d703236e86ebd23536a8af4d8f7b060519523ef1afbd65f342a5a191a7f100 mainnet-01582-de1cad89.era1 +ab1d6916d63d63e9daa34d90e36febfbe50642259b33c4fb9ed012e104746e8f mainnet-01583-2d72b6e4.era1 +a771a91cd9bd8419a46a5fa09153141acab84a0817a506a7c957f7a5082e28cc mainnet-01584-393498cd.era1 +adc1c64e9e02427ef348a135592f4c4bbcc903436387ace59e5bf28f6635fc92 mainnet-01585-fa098e6d.era1 +ef6aba72154d336723d100cba0948084f9e2a7ea1541f72c5138fdb6be2c13d6 mainnet-01586-379cb7fe.era1 +d0a6465c5fdac882bc85105dbdb28099830dfe60db68bf288d80911be215e795 mainnet-01587-62641130.era1 +ce7424f4a11798631796a5385aa390cf970d14d14ab9fc0e9a79919fc8c808aa mainnet-01588-63224c34.era1 +6be4cd261a1ec3c2f122e9c35d74fee83185021d89d1d42efe7adae8dde85665 mainnet-01589-a972b2e4.era1 +efd280edffc259d29d57cd36b89e34430f1fb956d4b90d37127f641b1a006063 mainnet-01590-1370376c.era1 +96bc3d9168aa98775bab57cc1de3de2765f233d633876acaf0e650cdf5ab8187 mainnet-01591-3c5940a5.era1 +4eb2803b800798fbf132a46d6a322a5e1d3c6f604c69c96b224368f88f1fbeaf mainnet-01592-fdcf0f05.era1 +902ac965eef864615dce6eccb5acde91b0da565512b646d1a4a53a450f41feff mainnet-01593-7779354b.era1 +df62bd03b138c1f024b3565cd5d5d9c9ffb86217b6279b6c5d39cfc1e16ad0db mainnet-01594-fc12f95b.era1 +b0a9fd005f6825f874b44b5da480046610142772cedb58c4be7fda04ff1bf2b1 mainnet-01595-2118c3d0.era1 +010782b7a091404af6232bc8768ac499423dfddb08ee1f62f9d47174b41aff5e mainnet-01596-f94bdd17.era1 +e8d40720e7be1738f3ef18c4af35e0f49e88ee61a55dc9d0e95ff024a90237a9 mainnet-01597-aeb7c436.era1 +31dc95aebdd1a2747077e52ad793d2e62a7cb69d77ebd19828074a15989b5d38 mainnet-01598-f56b793b.era1 +79f502abb89bb0eec42f3ab80847577e1e272f35f2203eac65b57729c77d27e0 mainnet-01599-6cf982a2.era1 +03fafb175c2a6a24c19f82ab9f94e06938bfb0f9cef9fcc94022ba23320f82f5 mainnet-01600-c6a9ee35.era1 +2e272107d43417600bca39785659ff66168182e38b2ed763becc5de3673fa22e mainnet-01601-0497bfd9.era1 +ebbec792fe3fdc063a260131febe6668a477ea7abccdfdb96ed8695832dbaf44 mainnet-01602-9a50fff5.era1 +a7282f54e8595b1d4c2abcbc64d378f418abdb1daced7a64b27e382168eb89b3 mainnet-01603-a1d88a26.era1 +dbf9264d64b6a8ed7b7c956f4f6d6588fabcc9dc447247b215d8c8cf16d36c85 mainnet-01604-00e0c17d.era1 +1100f28385ae46291c8f573b4e8c994eeee0609d230820089258fefa3ec104ca mainnet-01605-8fec155e.era1 +c99b73fdf1034c93bc879254190b3ec81f5d756481b2383998005865c1001625 mainnet-01606-7642a7d3.era1 +57248072c17b75b5ebb7ef087b9809cc08fc6e7e4d87a1bfe26789dcb4b2351b mainnet-01607-0a337fdb.era1 +89169750db27f32763c38701c7cd4ad2fbeaff06ceed6dec1dd69f8c71527a65 mainnet-01608-2b8f0227.era1 +b3d5edeb90bda42709bc5ff1793774c964c114d747d10d2e30d38875461f98f5 mainnet-01609-ceafb201.era1 +a0f60c0036177ba34aefd82bdd0c6d3d483279aa61a6b531cc62c275da00afed mainnet-01610-99fdde4b.era1 +6cb64bd1346e0a19fc61a73a100cd32389a54751147379d2e67936c7dc75d6b1 mainnet-01611-0d642ed6.era1 +3b6adbc75240ac148b57991e0c603bf1102f38021b48c8252760c2dfea463639 mainnet-01612-01a109f9.era1 +b0d5791e2c0e618beb451c897bcd2c8310e7d95e6db533a62ad720480e4003cd mainnet-01613-409c216e.era1 +cef35f80ebd7396e051e5c475c6aeea8721db6fa8f96b5e2d7c7aa0e52fe0b41 mainnet-01614-608abfc5.era1 +cc9e5f97cf1baf05026b9f366523a7257b762498d873189df8cceca0b48fa764 mainnet-01615-546296f9.era1 +9b9bd6c05c18a663aac7ef90f0b078d2278766710f13b720eb3ce0010d8991d9 mainnet-01616-210f4a03.era1 +3947b044d7275b95ce0d5c30c7522020d7e6ef63ca4477291ad1ee4ae0f2aab0 mainnet-01617-f300016d.era1 +2dd5cc29c9e516373bfbf690f37d6541f83d44530d5f1adbeb46f0d5f1ea4a8b mainnet-01618-d126355b.era1 +7e327c4c515a42c2c67a67ee85c40fe1a5fa55e28f9c066da63b262f62b4e740 mainnet-01619-fccf39ee.era1 +947f7d0ffde5c24358b6c924c54354bb35982e0324d81dad142b213a097bcbc6 mainnet-01620-62719ac2.era1 +7e82249cb9924bd9c7df57dc63917afa4247ae696b0e36b8548d5cc826425ddc mainnet-01621-d410e2d7.era1 +4a60acb269f942c6d6fc5edb66d09b8f40cf6003fb8ed2dd980ca6e9d4c78ee9 mainnet-01622-3a2643d1.era1 +83cb30fb9f530a63729e6632381adf1d1ea3d9790c1a8a3885493f14538b7a6d mainnet-01623-b86b68f1.era1 +f33d2dc5910930251ec6fa6663d608e14eaad79902a25b9e0e1c5923060cb451 mainnet-01624-79abcea6.era1 +4d978612c4d21afae90bca1876bad2a15e11d2529c0eb5519b7b8cdc24deef8a mainnet-01625-9d2445ad.era1 +6e73bf434de732e0aed33793de14dff42e6436685ec3ba9a012888877e812a01 mainnet-01626-a0719f02.era1 +0de06257af6217f6b1e48a4ecd834d2f0eb38e7dc3f11350bda7403820956482 mainnet-01627-3825eb62.era1 +5750b01adf5e5db444ec333ec9de9d65419010007df44a362f58b59dad668fcc mainnet-01628-49d1a71d.era1 +206bf4ddd8c95816e9116daef0c06a547d208a43d1dd42041b799aa37881785e mainnet-01629-1ec93093.era1 +1d8eb98edaca0ff1ec5ce89dc6e9dc46454e9f90fef71f1d0df94b3016d95fa5 mainnet-01630-d52d9f3e.era1 +56c5864a3e6f2fbbb66b38eb35243d00522222e47cbc17c798e861d4323818b9 mainnet-01631-438a5c23.era1 +09b7d3e9e045731a6889a463e2cbafbd4bd459eb0e1dc19dc188c0396f2093fc mainnet-01632-b811a1ab.era1 +0b9a9ae0174a8cd5d0ea944001d43dd2c919ff62039662ef4ba3397f1791abc1 mainnet-01633-2dba253d.era1 +55c727428d8d8d2b2a4233b3ff9cb5fea6c66c23090350f49aa2fbc53b79636b mainnet-01634-c0975217.era1 +83a255aff9d3c7defd78d7c17850ce4df4ad2c10f114a0a5d40a75f099baaa4b mainnet-01635-926f0429.era1 +edcd2e9493d70b3498a113159ea7548075d5f6ba03ec7dc441447688ed207d65 mainnet-01636-88bc22af.era1 +68d93f5aa6c13075badba3c6fae3ae8bc0fa357a80b9bd1539cb249d9c414879 mainnet-01637-d10229ae.era1 +d18c50eb79436b9e960c8fd12fdff6925d901dd8e2c26f4e08dd4178b8e3e1a1 mainnet-01638-f60a479f.era1 +91baa2e3f7ebed254f3753afdb5c8e9666553e77c7cd651aacefcc97c453bf65 mainnet-01639-45574d29.era1 +6d2f5a87fec391b024b77ded2cee7f2c9647dea36d48a5d7876ad59180e3cdce mainnet-01640-f4d925c6.era1 +1cffb9c6dd88abf72b7746754950a27d8e215715d44c402de5b61838aa7186f4 mainnet-01641-05561645.era1 +438300a7f95a8ae17aa27b64d6500c70e6b2ffb908f968879772f6321b17660a mainnet-01642-bffe5d04.era1 +fde6789e767f290c4734b9bb96704029923f2c6094ce2458e8642af7227669ac mainnet-01643-db04ce69.era1 +20b99f2db27430968a5f22db2148d37abb048e5733349336241a62782b33d35d mainnet-01644-836dd3c2.era1 +78d93ddb94df9a2595706c2b7a622d90b8f06c407af9d5a895b09bb625732c09 mainnet-01645-ccdd4d37.era1 +e855b060e1cee6387a7ce6b2681f1c3af5ea6803a362efd422f3313a32046dc8 mainnet-01646-df78d1aa.era1 +28e21deae06a082bd6ad582c893960e0cb5559de8c6f003a627dffb4a4ea302f mainnet-01647-bc1a2596.era1 +e4ed9e14f0d72f721289c4e806a6d07e6edf81a01b05b9ef7953ae8e155c40e6 mainnet-01648-ba444550.era1 +b005a1085fae3f049796cca6076dee3cdc246d798b1449b6ac696646ece3c1bc mainnet-01649-c772985e.era1 +6499d2ce493545fd5ac85e0aae30ce766c08ba6aaca6b7a94fa61089834ff422 mainnet-01650-0cd44f84.era1 +d2e6f7286e6380b83118d83d27b9bcb6d05b4664af7c79a0ba930c0d19e74db5 mainnet-01651-108b8139.era1 +06b4cee7d62b17bae99db042addddec5fbc97bd7b882c2ccebc2bfbe09d9971b mainnet-01652-92dc53a4.era1 +1a72131ec11e08bf5e482c006804e56e2ba7b1586f6c8cfb30144fe66a1eb2ff mainnet-01653-ac1c8ccb.era1 +01c2b842a7eaf97c1244ad6ab451aaa6384c58dd2311a429242603fef836246d mainnet-01654-2f466ff6.era1 +35a9484fd611163daa74558d7be708e0e262eeb17270235fe61da80b6e5baae1 mainnet-01655-4dc5edd2.era1 +96837fa185b1e407429e2eae00e0cc40af64b3a9b51dbdb9fc83002e1e62730f mainnet-01656-72d321b5.era1 +e4bfb4fee82e660922baa7a7a0b4073739f863d5a82d447f1b2e2c14d96ee4f6 mainnet-01657-d0684723.era1 +38274fd658e3a2225814dab185807334c4a2377fe00952935f41103453bbe7df mainnet-01658-651f1c70.era1 +4352318a3c8a480a115d081afe9e37711e997f96904722efdcc23cf16401a4d8 mainnet-01659-0013c08b.era1 +e101cedb4dc4dc0427182376ad6cbf02a4b5ccac9fa079425819481b526080e6 mainnet-01660-7825d5b2.era1 +a06e6331b045cba8ca1a31edc83f30e4de2e6abbdd310f11e9995b2515f7990d mainnet-01661-84e21383.era1 +cf84a100eec66094997768ba35ee2d39d670c98ccfcc50eecf04692441af6fe8 mainnet-01662-a5681587.era1 +a837dcd4cdd8917d21032e9b45f2a7688d527810c4321dda9bb8530f52ef9d10 mainnet-01663-c84283fa.era1 +4dd4b08e0577e72febcb904f542ecdd239b2fdc6c37aa9900e937319f2e9e6d0 mainnet-01664-ab3af7a0.era1 +18428df15b49400723296f714c964a6c0a7f553cf70643a0c77c13ec9338dd53 mainnet-01665-d0adeec0.era1 +4391c6ff4a21e044e07acd9b2a34277fa903b26c52ddb4563be7bafd611cedc5 mainnet-01666-827de27e.era1 +e46ab921179e9f1ce080f2d9e9cdfd5fbc1fe86c324b7daa04a3be0a75f7070e mainnet-01667-558e2125.era1 +aea3af1e83809aca973445cb92d437fdd6c3277ec37ba5530dc68d1c1186a82c mainnet-01668-8d75bc10.era1 +0d1b9b762a6acc59cfe20ce1444ceba7b28aac87a367d8ad867c75acae1242f2 mainnet-01669-84ccda7e.era1 +4d273107762c163b629e1f1c93be2a90788db4534c1ee47caf3d201a1a3bb39a mainnet-01670-3490d679.era1 +e974b0c2a4119dc0b933dcc3a57bdb5d0c9b1058090a98fedcfbfbb775bad598 mainnet-01671-4533f7b3.era1 +9b9fe120f05946ba3755cb8a1a407c1473f12ecb48caac7d082983a7f23de120 mainnet-01672-abf10629.era1 +b35de36af93d752a2d0a3c2661f75945418f069f0cb4d3bfbf43834593274e9b mainnet-01673-d67018bd.era1 +29962e598e4aa1445f1cdcfc71228ecff08a9dc716ed22bb33bcf504586ed060 mainnet-01674-16b9e877.era1 +b4210ce62e93c251b47b9baf4a35ca2c512064f4461d10af2e681901ec888b74 mainnet-01675-35b0af7b.era1 +ac0a3ede1bad8761005d2f4ba0e29b47d46899039c30e6e65116daf06302c713 mainnet-01676-2753d9cd.era1 +913ed37b7280c0488f0b2de53bf8186c872b861bd1661e81a99834d4129aeffe mainnet-01677-e40b2ea4.era1 +2bc0af84a6edc0a2af8bdf9ac47d80a68b05241a9caa4404ea55a9822e48302b mainnet-01678-fcbdf0e3.era1 +63f5cee3827ce44ec03a277bb6af7e806ba240a59541fc9b36362b4089a8025d mainnet-01679-e5f342e2.era1 +df44e2d0aa327e3fd223579886f0da34b5c760bd4062202d2a565215b81ea528 mainnet-01680-af511202.era1 +a6c893c0bf0cfb25566d230ce2e9e701702826c670b58757a0122bb2c80c3f68 mainnet-01681-d0e6d3d3.era1 +d36179575d40b3c0d77d1baf8bb54d9db4029da6c917a157ffd42186b7c8ff00 mainnet-01682-66ddcfa8.era1 +977c03ba488a3aa991bd54b335b103df2b19039358736e77c2bb62c9bd61e6e8 mainnet-01683-8887a5b6.era1 +350e7911f40b1691f883cf1a45e5f1c5af895b4e6c69741b8b8630edef1342c0 mainnet-01684-bb0ab38c.era1 +42005763913f34a9f40a30bf34cfa29d33e4afbc8e37bdd5b59037211609e59c mainnet-01685-64bf045d.era1 +efaf03b1a2ce0c90ee6820aecafa4dc3c5a842938eea67b8682a7dee5a54d301 mainnet-01686-7a8fba5b.era1 +c110709475eab96bf1199fc05f12b1e93934bbe913578eee747c8a6c2dad38ee mainnet-01687-26481dad.era1 +e17e1ada1db485936003d7ac7e39adbb61ee1603e5ae612eab56434836eb98fc mainnet-01688-05f0a174.era1 +0a7ba360649c251244495f591840e2d6fd5573a78e3c722cd893955c2a28ad7d mainnet-01689-ac53e2ec.era1 +e08c6a38b0388a831182bc1ce40138fed2a801ad1c2630af40ac65c099414ad9 mainnet-01690-9dbcd976.era1 +a9c29e89fc7ce6ad5be4fd1d4549299d627c03bdb238372d73c3d9be25f12675 mainnet-01691-bb315f50.era1 +2ad967654e2f974e258e44b6754a77f56cba0afe8ccaa15fc439fbc12798c693 mainnet-01692-b877548b.era1 +106ef010fd0d5aaee7a0403d87e0f23ecfa645393b8c2bdc9e015afbd11497ba mainnet-01693-3d2c2aad.era1 +e35d0448682fb19310974dd10afe35e15e3ff72cdcc274e522a1d39ac48b1893 mainnet-01694-d42cdf89.era1 +3660dc81c12ae17c90ad39c60d53d66ae434b7501e2ef471241736a392e7f16b mainnet-01695-8d97b217.era1 +8ad51c98a5383b4f1b8cd4daa76e0cb06efb757442b2aa60051e30cfbf4936e9 mainnet-01696-49e0b594.era1 +31804fc49af12294cae633abefbb2deeb3edd68a8d88025bce280bf73e564e7f mainnet-01697-01b23d08.era1 +1e9a9b43703a4204766e4a7c5417239e70fada858f1d6736048c5098f4138c62 mainnet-01698-9c316b67.era1 +cb7065153c0805f9067abc909fa30e2710bc8ac5daf1e2b8a91f21ef58aa1d82 mainnet-01699-cea5c210.era1 +3ad35b036db0a06fd8f5643920e932a18c934a3a48211d0d29821fc5be1c62d4 mainnet-01700-3d9833e9.era1 +8f53349a041f87bbdabc195e8a5a8b5a6a298dea93a793bb06e8875bb720b673 mainnet-01701-073ad3dc.era1 +dfa4e8dfd877609aaa5cf823d6c6451521ce52b6ace31b9dd4709c1660d3380d mainnet-01702-9c454cbc.era1 +20e5075f81c16f0646712c90db5adf2bc7d700cb85eaeae6fd20ca25eeaf1c69 mainnet-01703-0d424bdb.era1 +d3c36455190c49fed972a9cca857b8003de46f05d60c6e274b3476987ce5b806 mainnet-01704-c8426624.era1 +a9c26e0771f6434853d481b5989dace7ab3bdac64b09236127fb8a776d11a908 mainnet-01705-850425a7.era1 +e1280b5098b064e034d683dde04136fde1501092956a2d1326e4332ac8050aa1 mainnet-01706-5f7468d2.era1 +c4797f0d3596853c7f8467a34216cae9c96577cd89e7a417cd11aa9faddeb8f5 mainnet-01707-68199dcd.era1 +001a05c2058846729183727e9e2f5c88c6a2ed60effa7fcaad1a065fee12e296 mainnet-01708-1bc39088.era1 +c5659c0e1114fcbd5d3e6fa7df0af74bef56a6e16b6ce39e161d710b02318644 mainnet-01709-ac6bdf4c.era1 +cdb9ec5a2786d0f8ec381e7196b8f29ec52dc115090f48262a06cfd5688ac477 mainnet-01710-616a4213.era1 +aff691d78a906fb94516900a6e00971fd804eeea5266fbb447a0fc02183652ee mainnet-01711-675a2efc.era1 +142053135f5bf9c9a08b04039c68a4172330bf4703867603f4d8e2882da1d602 mainnet-01712-b3466ce1.era1 +2351634486ff7748d00b61b4120b8bdaa5521098b5d2da3d0d59c0d13b92f054 mainnet-01713-efe87a15.era1 +d8a5922f7d26e436321ba56ffc2923fc0be6299d632f1f17befd6f99e4a63966 mainnet-01714-8a93b06d.era1 +63e092eec59ff940754f0f05dc96a053d6929a1da224a264dd2e9a0bf3ebfd25 mainnet-01715-c53f6fe8.era1 +54ef87fde748440e0347ff7c3e339691f75c664c93de1658b6f9111cc0403e89 mainnet-01716-beebbc85.era1 +b5d541673d8f32aa5041c5d46459b3423896fecc9568b1fc9c2b8468cc7892aa mainnet-01717-2daba19a.era1 +6ed9fee8c53ab7a9c16ed490aeee51f2d5a78393d670f288dfd77f36d4967d81 mainnet-01718-69ddf701.era1 +831c00c3a6325a2c7ef613d965e0b4bbfd67c64822e634844c27088beb059c21 mainnet-01719-ac2ebcf4.era1 +054fdc70c1d020bd1a910c6ec22351b95067001a52767921f460f2993ff4522e mainnet-01720-c428eb52.era1 +6b3ea18780edf83f361fe2d3a17c53303868c5c4c46a8139ba003f332fc28676 mainnet-01721-940116ce.era1 +fd954f67fbaa219ea51fb592c34c1ffec066002b824bf18e6614c673eee598bf mainnet-01722-1aff873b.era1 +2511305a5ce78ad72aa9dbdad9817e8469a295dcbb5984a957aece48930a0195 mainnet-01723-f19dc7c1.era1 +4c36e22cee8ddbcaf18d09e596cec9a92a3f0a45f3fe65b57aa0706af2f5fb23 mainnet-01724-50ba9e24.era1 +d1aa0d2d92ab9eb9bd387b15c77b9f0221be2a767f86f1b7b9309de24fbb76b8 mainnet-01725-6244c9ba.era1 +f31545c2b115d0c0eebf6d80b1bcfd78598ae06f1986df5efdcfc3d4f37b7ed1 mainnet-01726-d9ca0531.era1 +78004f7204f2e7ac123860e3d5ca0776498e8253d01ace192c0f3ebda61a5ab8 mainnet-01727-019f04b7.era1 +15a6bd053f3a88335e91d6c6442d72eaaccb0d57c7ff2dfc9f17ff3c07fa865e mainnet-01728-0bd9139d.era1 +d5b5ba3f562642fb45208da6733142293472cbda4b99fc6e984955595efd1fc9 mainnet-01729-a85a5ebe.era1 +6e49421a232ca1b641ddbe56383bc74982b163b86d41aca834473134c4610cd1 mainnet-01730-e07d8fc1.era1 +477eac763c868cf1ac6259e07c633774ea0f08c64d3ca04687074bb18a419e1a mainnet-01731-cdeae685.era1 +ca68cdf760dbad25ad5ef8bdaf85b0058de563632136f7fe9d2d95a04bfe339f mainnet-01732-d4b05748.era1 +06b1c9f0c06d35ce43c35df229c1d6faf8c79a2b402bbed4f130065531ee7835 mainnet-01733-2b75c3c9.era1 +4a954844ebcc4b0f0c94ca52547190210f649f72bcdb9f80d1d3d4e71f74ce1b mainnet-01734-0b51aa4b.era1 +330fb8fdd3c5aabae38c66750176f804e9c07bbc4bde6455d2c43afbb6db8800 mainnet-01735-5b7da9fd.era1 +d2add601504ca241728d9b8432aac9a6d369d207c54cca01c7d49bbf7c48c0ea mainnet-01736-2d581b43.era1 +7346d0e283a184e99980cec04b06e311719f4f29c18b2012fe37128c2a19711b mainnet-01737-053468cb.era1 +259d8dfb172a6b0dec07c12c1fab578d7a7518902cb12e42423732d81203d37a mainnet-01738-c4ea7355.era1 +cea5a2851704064b8fd19552ecaf48de00beafdc4ae82c37f4a2082e11b43015 mainnet-01739-390296d2.era1 +9a57cb258cc2dd09ce7b55e09f2f260bb73c7c71aaca242048fa60ed02354acf mainnet-01740-0bc99a43.era1 +caa75f9f4de04adfc7e12807d84de63a0d25d5f9ad526af13c748ba0cbe12469 mainnet-01741-831ca140.era1 +814ea7efaee9fd9f538c120e23c5da3f179cdf7d657335e34940506e24b466e0 mainnet-01742-6ea854bc.era1 +4a80a24474e75c813ece60c103e053f33d5d0e56b40ce212361ee914232cb078 mainnet-01743-cbe74e16.era1 +444335c8e046badc93ef4cfd8da27ffcbbde62a739874c9a133d6a1aee184436 mainnet-01744-afde3d1a.era1 +4f49ec87006142e56afa1208efe10c3e57b671a7995bddb5d2e52d8814f30115 mainnet-01745-265425af.era1 +98484f5a5cd6307bd21db41c280cc8e26e343c648db6b83fc3dc76770ab97b99 mainnet-01746-ffa83edd.era1 +86e82209a82218f8d477c84622831fb7a985f8995fe7bc2c9a3f1dddd2f509cc mainnet-01747-2d7f0f5a.era1 +147366fe1cf8a15b86df6e2057b6197efd6291e5a1c02130697b395f9579a084 mainnet-01748-7b69dcfe.era1 +bb8718154e5cfbdc3851e1bd92d25d0c7c1f6caa408b247fa23aeff123e70bb4 mainnet-01749-c08c9611.era1 +ea12b0e1908f4992cf34a041e1ddb828a28a2d896917e3cdc1accb7be1bacb57 mainnet-01750-6067e2da.era1 +d457cc2a7f6dc98768f427366b7062b5c18394e60b39873a11001f0eecde22b5 mainnet-01751-50262a09.era1 +44cb9be229a4a0f73f0ffbb979adfafea36a0a2b04cf45bf06f8cdc73d47a770 mainnet-01752-0488926e.era1 +29642c796b4ac6fe40e42ba781c3f1cd973eed1b333bd18d8fea12fac869f04d mainnet-01753-7477c0a1.era1 +c72f3c3be651e63836a45aac5a2ebfaeeddc84c5623fe55c9040725503580398 mainnet-01754-646def35.era1 +390aab178f3fa64c3f7c9d49a168cfd4864406d98479a1262fe4639877f932a1 mainnet-01755-84f4fc01.era1 +00809821d0ac264ceeca9cde077b30a7d7bbc090680b72bcce0b7a3e352dc675 mainnet-01756-308e0580.era1 +ab7d0b5eba4e9362a3beae38f4c9cfedf1eb7e953ef541019c0d3779a92d2ff1 mainnet-01757-8b98854f.era1 +b5d44da8b08efd4d49f08a069a329877344304d0db8f031d3748090e73ef1c9d mainnet-01758-7c7bd992.era1 +039f94e36edc9664ba94554e943f5e1e3832fc3c2367b915cab73702a2ddfabb mainnet-01759-ef9dd1ae.era1 +3b00ec14cfec68038f9b09d0e471472a543b7e81c5b195aa0d49be1064b733c3 mainnet-01760-c908c0cb.era1 +7d7ba43a3b5d3d07083c5c3764f3062f19adabc13ea0e91a71bc164ba058e8a0 mainnet-01761-4c223079.era1 +690a0ac75a9478e85925efa16fc3c773fc108ea10d993ca64a7fcf1ead7ed4e7 mainnet-01762-58e9482f.era1 +a206d2ee6859a7941e7bf3adcdd01b954a6f1e99258f05cc6c1d1badeb94e1b1 mainnet-01763-e9b64e43.era1 +61221de714d558e1d478b269e4ac07246d2ee4d563f0121297e5cda10eca8b71 mainnet-01764-69d58dfd.era1 +a2c885b3dd2e7bb137983721941c5330d50134568c96bea6dd84335ba29b0a64 mainnet-01765-56508960.era1 +4ec349b6cfa62117f3e22f5d6876bad0cd33b7dec29517e429e5a8f986368129 mainnet-01766-e47ad77c.era1 +54cfd1f1b777197a0baf6b8856a898b37dc9395a449f605ef344b1cf0f21365d mainnet-01767-c92526a4.era1 +56f8a3ca394e71021db7502256d1725de65913549bf948f9b9309e13034b50e9 mainnet-01768-0f318bcd.era1 +a6e19802b345ad2eefc4643b2f2cfff050d95ecb2f571fb83b3347c2e387e19d mainnet-01769-cc56b7c7.era1 +92b9eab7566de2d1bd81bb87737b5695d37a10913daeacf8ee8626c48e6a4dab mainnet-01770-8a0d9bcd.era1 +9837b0e62989fa89b8365c58de124b132aaa0a02db4f2f9925d609d5cbf7cd70 mainnet-01771-8c0c7922.era1 +f1f5657d4d74fe786d08b9b84f4aeb2e8e1229ed79284b95bcf3978506aa9aeb mainnet-01772-490072e1.era1 +5c9e6d7f79d6b66d869184db4f737facefc8a77656500f7cf70d1e24cb781ca3 mainnet-01773-441a3c8c.era1 +11bf26b1e892ecb5fb1bc2fa901d76fb3b80a5d2f1244a9bfa97734a7fbf3d20 mainnet-01774-9d3c41ed.era1 +abdffb40e251c5519e279f29e3457ff35e1940587353f6af98e85ed6ee0ef2b1 mainnet-01775-6023b5ad.era1 +8207baec682cafc0bd49f8374a27dc42e8438c91250f6fad4984386cdb938bad mainnet-01776-848902b0.era1 +ad7cc2dac5c009b4478f2e7af83f7742e1b118e01c66d5b301563a0dcc9bca34 mainnet-01777-56f9c62b.era1 +10242c34bf2105d577e40e835c49eba8ce00e330f4027875a7a2dd31c175bb87 mainnet-01778-01a7fc06.era1 +def53a3865dd9824c40a2a2ac918f1d68f6fe44be12fb32d70a3c6f0dd79ad35 mainnet-01779-9ff0b054.era1 +cff7bb320ad2df3c95e50b28f36f4cd08080036f6e3487f763a14a8a3c736a6c mainnet-01780-0601be62.era1 +908ba078f115308795bb316a04eb26fbf2c6ad6ee70c8013b222f9b88d1fc25c mainnet-01781-c73b916a.era1 +d54d51b9943469b3f98d41fc032966326a0284a196758d9a97ec25d9b503be0a mainnet-01782-4ff9deb8.era1 +e5ef6720d4344b8172b8c5e3e65314137c72a2cf8d8df3ac67ba1ff348c081eb mainnet-01783-6dcf0704.era1 +ff9d6f57135bafa3744ffd3562495937dc479b5e466fecd128bffffb354d4bde mainnet-01784-37725e0b.era1 +1626ff1b25cbd8d365ef179d760206d2f3a7e34283ad89e0c3de76682a4a8c9b mainnet-01785-bb264cc3.era1 +e8139e73f730e001fcd2c95f4d100401841d13fefc7abdd3d0da7b32cffb1d44 mainnet-01786-8f3dccda.era1 +ca3bfe0711d28fb7a43d9a37a6802cbb53a23a03855de31e45b3a2282f4dca00 mainnet-01787-8cae5bdc.era1 +2c05e0edf4cafea94575d5ddc29d9db3e9af79ffca259a1e1fc34ae1d8efdf8f mainnet-01788-7e1c1704.era1 +1ff17cc6dbb42da4be0c4c312a55cce95ed32829a332e888b8e999807327ac18 mainnet-01789-db34d4b8.era1 +e7df0305b5fd13fafb69b72ecf65715086ca9dfd9b5b0a60949cb4fb93e8a513 mainnet-01790-0e2fc599.era1 +972f33b700efda3b51dd8e7ba4285bbfd735c0caac70669c26c663cd5f428b23 mainnet-01791-0dabc8f4.era1 +2c203a477905059a0ddf15f23cdb0a6af453706542fc23547347ccc6f35e61b7 mainnet-01792-648d0dd2.era1 +c140566f729c7234daa27aca935c23b94264750db2e5c31ce51328531933656a mainnet-01793-77485ef3.era1 +5919ad8de00445b2dc6889583151806527b3da2933098324442036d19559f9ea mainnet-01794-e291673e.era1 +b8be8c99dff125973899bf7aa1afe6781416df937f5226e4d4cb3215953f2093 mainnet-01795-d1d496b1.era1 +b86336614b33a78c996f4d336d4228384b202ee1b7252eac6077d4e8393f6754 mainnet-01796-33a5546b.era1 +08bba1af8d0185a153b55ee9f0cdb03294c6521523d4bae4d9ef2e91553af78c mainnet-01797-34123297.era1 +9db3986e4738134b2f924332b8e3b9fff78735be682326ce0a60425df0f8abc3 mainnet-01798-3ca0aead.era1 +e71d18586ae068704b0a70c226559e49334ad35b90adeb21e0e6a6497ef71280 mainnet-01799-e949b50c.era1 +169ef20cc0417506badbe99059319fb2e075d41348b589f831041b43f93e4601 mainnet-01800-07cb6fc5.era1 +3b6ac2d372e4f7d086f414aede4fcd85ab99eecd5b8813de28374dd4395a9474 mainnet-01801-8edf5827.era1 +373d59a8877cbd8b04a7fdcde7b622255add49295b6bb0e6798f96742f14aec4 mainnet-01802-f95306bb.era1 +ffb419fdb5ef8b1751582d9bffe0d415a8f3575fcf3637c6e3f318ae339146f7 mainnet-01803-4e1d05e2.era1 +817da39985c59490e5e5c9d552800210bb63ac4bcbe69e5660d2197c7645520d mainnet-01804-a24b5a4a.era1 +96e1f8b663ee8858688c96c680a7b50fc5b4ab6e417de66804cc37ebab61d83b mainnet-01805-81d9a952.era1 +7cd6588b9de8c36552aa5720f1eef8befb529348a28e2b12bc24dc62dfdce32b mainnet-01806-66534ad9.era1 +28733727ad69c62d6cb996c7ba56ce877228cc13b49404c58480f5744e1b2f42 mainnet-01807-37ac1801.era1 +11d4f6cdde3fab436ee0860524869d550a296973a16123564cc378fd6b8fb76b mainnet-01808-3f1a883d.era1 +f134e7b5a1dab190a560976c49d44af0bf4b29ecdf90b5956e68ef1fc5873b07 mainnet-01809-45d0f53f.era1 +7d896a5ee60a4538daddfd3224ee1733ffe03ce2d9205fbb8bcdd5556880cd18 mainnet-01810-6ccaab76.era1 +97270e0c74daf2b6dce276f7e57da1675686898f5fe6e71b41372a5ed71b2861 mainnet-01811-9ab98ad9.era1 +128b576e331eb6dd13669fd41ad838a55234ba8fd551b540334aaa5977a25839 mainnet-01812-80d86e96.era1 +94b8405c2ca5e927fe04c53abad00195af8f5ddcaabd5bcb380ebacb974d0f0b mainnet-01813-1b4ae400.era1 +bcbfc951eb5accdfc901c2d4e09bed8c2dd8527523ddf5168bde7f6cafb65665 mainnet-01814-e0064cce.era1 +9cae44c640a4eedfd0203544557b9859fad78525315fea016f0760fee9621c68 mainnet-01815-a2d04240.era1 +bd0d76e3aacd16bca11fdf97f3c4d59d6c94d2c6632336b409a17362e18a7149 mainnet-01816-9a493dd7.era1 +e1e52b715b706fb6a51fd475c90ffe844c05af4682212dc735b70eb6d15b8c7b mainnet-01817-f534c5f3.era1 +47d4d64d864b2899d7de2579c51313938e0ff0fa9138b2243a5ddb52f9dfdf7f mainnet-01818-c34b86c6.era1 +b3e560f0cf07d7eef8e791bc06dd9641c7c7735d4236dcb2a36b21eec1a197c0 mainnet-01819-918b86fa.era1 +9f731bd11450d62258465e82551e0880cb069ce742ae13bde68dea2601721748 mainnet-01820-17e7111c.era1 +d6f23c1501e8f32f0684225a3c127c72315a8fc456bcbf92cdc217eed2a84d33 mainnet-01821-e118ce72.era1 +5f3e345b1e4de32db962e04b1a634bf7a5015fe1cc37e19fd65cc29a78d49ec9 mainnet-01822-d7b7b15d.era1 +6d2414fb6da3b2cb1b6ed24a68cef0b3e57f4d6a8b2f0c5a90c03c4cd02cedcf mainnet-01823-3fe7a945.era1 +0ea96886a709d1e7ea834c4a524b07b75dc235cf34d6819812929067511301a3 mainnet-01824-6ad87d35.era1 +c612eab2bb1cee468887caff7032f5fd6a09a297ede51e25c2100cc46f82fa1f mainnet-01825-7f981244.era1 +0fb454e3e2d97d1d136ad2f026926b9340cf0a338e2bce065274b5b699fdd99a mainnet-01826-c17dc5a3.era1 +f01b822341df294990d8f41a1d9ddc3a99f77614fdbb06882a3efbde0470ca61 mainnet-01827-fa5fbccb.era1 +dc618a87935f5b1c5a7dafeb662c8672a9548c387d1bf856f0c9ab47ad430e23 mainnet-01828-540009e5.era1 +7097ea8556d18ada8179df1a19b9979230dd60b101448242fe0f715efe087593 mainnet-01829-41ed6fe7.era1 +dd6a8b10bf7d6a29d83be0ca90812865496bb76501e6f42d4abf3b8df3cbc380 mainnet-01830-2afebfec.era1 +5dedcfe545ca0511c90ef476e003381a11aa60164579d750b19ebf38a4114159 mainnet-01831-7289db8d.era1 +600a782467d1fb81a455d097a0a5e877b2fcef41d39a2eabc50c8079c768615c mainnet-01832-b1198d24.era1 +ffe32e137d93df3c83d498a8af890369979255326fd8955e93849772304732fe mainnet-01833-0bef1261.era1 +e8d69bf28daf5c338649528feb91b91635d686144caa6b302d4f2ccbf63887c8 mainnet-01834-fdca337f.era1 +4f97a53b046804e68bede066b1648d83ef18c90f0849e15963e3ac70a9441c26 mainnet-01835-a45d06ec.era1 +17cbe71911e869e1180fa3f4e9f428f62a2305c6c86f7b9e3eeaeabc7e4cb4e3 mainnet-01836-87fe297b.era1 +2d02765b6d417d1800dd62d9057e933c21eb7440c075cc8de5d8a8e2e0b8e13b mainnet-01837-e26e40bd.era1 +133f804d8f0fcb26fdb49cc1d10ddf51dbe1214e1e7ffd622b72d96fe8170029 mainnet-01838-ec6b0c03.era1 +351b5e8110203c9095b32a38090e5643da57b48038d4dd84480816cd4550ff7c mainnet-01839-07950048.era1 +161f66a9d95eede26f873efa400763d90b638521268f89c9316462356161a2b8 mainnet-01840-e287972b.era1 +17ff39336044d08693519e82319b3aebcbc78e179068520d5feddca7407ea7bd mainnet-01841-2a6039e5.era1 +c882be49dedfa2ddfabf14b1d7ac3ea64e62fae051d5eb93f0caea9b1b8fbc17 mainnet-01842-5567d80f.era1 +feb4455e45319b835135110b67da829745bdaba876f5e8ad518a77189e0bec4e mainnet-01843-3153e10a.era1 +1a205dddfdd1fb0341bc260b8f2a6fe210d274f18bd1d7f650a2c475f3f9a71a mainnet-01844-03b0963d.era1 +622530320567648c3bf30a111c3e8f0c38a236772313d29f280179c2d02197ea mainnet-01845-03b93b15.era1 +eb797fcc91cd6154d60230772ca77fff747a7054a2867cf7b8d8393abdb6d577 mainnet-01846-3e05673e.era1 +82cd487fafe6d8604d9c9725bbe9452f95e026e86d76b3239b6d3e4b7146bb50 mainnet-01847-2de5f285.era1 +21045bf78b5fa1f63d746908c8677e4bcfe33ed33fe3c5388d3b46dedd945fae mainnet-01848-113a0599.era1 +7a1f6b831f2f06761fac5f630b22c38ca8cd6ffb95e14d4b23ec7229dc27945c mainnet-01849-71675e40.era1 +6dc1341e050c93d17c63b041c0135c97d5b8ed492cc386aa12b9805d71abf2bd mainnet-01850-eb0e8dce.era1 +774e428b959db0a51682351a5a68349794eb61d5f5899a2aa642c63d85b55f46 mainnet-01851-27b488ec.era1 +fb66711c88759a426d60bd0793589799c46c0275aff4957a9b46eb1b0315c940 mainnet-01852-a405f5f3.era1 +74ffea8a7f9694760b7ff2a368f5111b816813591182d44008551d5ce7a5c3f6 mainnet-01853-de7294f5.era1 +315a725314b5b8c1a00ee93fc0bb7e17166885e2daa8ef1d4abf72fdc0c02099 mainnet-01854-1b3a9f72.era1 +977941463e01f6a0a06cb7c30e6799755ef1b98b0cf8e47fb2957b4a2360345d mainnet-01855-bb986915.era1 +842ac3df8762f07afb910ab82cb89101418636f13c54d31d21e978c15fa8b246 mainnet-01856-10e8b0ee.era1 +0ed37c5b1df966e68716fa4b2c0328c2738262721fb0da19fc87ec9fd3441fb9 mainnet-01857-e0a70c38.era1 +1d419c191e93d5915e7e1a39ac7a4d1a6b5e5111f7ce772bc9c9d2bf09f0bef9 mainnet-01858-96299d52.era1 +fef06b6aae88746a73d84aae756c7073f3f7378a89c80b5629d4cbc7ba004fed mainnet-01859-056f7f9b.era1 +3d5329a9404c468f64482bd8c76ad05fd3b769cf3e1ada43910c367eec4f3f09 mainnet-01860-be17dd25.era1 +0b421c693e9d5c747b8348ce9d236e70592f5817c7f7f8ab2b579fd5d8461f67 mainnet-01861-31641a08.era1 +16c9d7c2c498f72d1336c86f477ac4ce4c1cd65fedee0cbbc196a15cfc47d4a0 mainnet-01862-deb651e1.era1 +abee7f8f73830a9a8a0eeccd6ea82abf6eb9fdaa1c58c79b95832c98c273586e mainnet-01863-500103a0.era1 +6af0acfc1ea37b531aa8cfbfaee8c99277b10ead6ceb3b19e6cdaa3bd01825a0 mainnet-01864-168be6df.era1 +7494fabb5f9f94f5afafc82ac7ef40739f8b4f74003bbabd286a8f51716920ee mainnet-01865-d69771c5.era1 +29334e8e24b5b98bfddb7f25b2c1dd31ad51d325c9613eb6210112281f1eb1ce mainnet-01866-3cf6a306.era1 +dffd7716b669261690556826cd8b21da2197ef3e98ad21cedbe9623e4f41d998 mainnet-01867-69891a16.era1 +34bda1f8771b070b95ef1ea62b49dccbd3b987f10531cf65ac18bf95ce20e415 mainnet-01868-fb7b596a.era1 +48b4ce8201c4c0e6d3dc7e079f3e87745fd6260d70cf89d210b17cf30d079b85 mainnet-01869-d864488d.era1 +8aa2f4333d0f21601874d7525ee983489b861d3198124db45ac9b6b922e609e6 mainnet-01870-3dc73a6d.era1 +5284fd43ca889845d07bac332cddc9c183e1a9a90c4281c18e1cfc00734c3a27 mainnet-01871-ca53dc21.era1 +63a6f4f1e593247cadb590ea238ca9d613c0fff308331fb7a85239cd8c4eec66 mainnet-01872-d571c79a.era1 +ca798432a63ae6b761cf9e90a98f94add78b4e292d8bd8287e3425a7b7a34c5e mainnet-01873-c71b3cef.era1 +c2134b7fa84e04548facd1d22d7f6193805a03785258bb9f2240b67afe6ebacd mainnet-01874-b43aeeec.era1 +52fd98bfa5b8a99416e1d27968215180adb0be009b6efdb22a4d3ead0349134d mainnet-01875-24fb7782.era1 +103b8e5d17b21ded74f53be236713cb8a9be4fe935ffc246a746417272d1102a mainnet-01876-41ac34f8.era1 +8b0e3abe1b964e612fae21238ebe7cb4a9070c3bda35f3aae8b31dafa907fab2 mainnet-01877-54983d68.era1 +6a16105b29fbe23cf69d902dc2cffa79f3beaf359d5b0a5d2b58789f34cc4f0a mainnet-01878-56db2145.era1 +7f73eb9fcdfb4cfc7dc9bb2cc8f0ea0498298a65eed71686102e0a695ea1a23d mainnet-01879-793c08df.era1 +41c749a4adbcb134050ff91a5d2ec6a28d33682700e294e949fd68b1dd88e4b3 mainnet-01880-0412a89e.era1 +177c549d6b99ea7ab2607343e4ba70d2a203773c43776876d1f337c5c635680f mainnet-01881-8d991285.era1 +163b67fa36d84a677985407c40f5197d7263f3d24fc3a0954bf6a8158f80dfc0 mainnet-01882-44df0aab.era1 +94b4d2fc661d91d6ef54366fccf40927dd99073564cf8b4a43127c9162dca41a mainnet-01883-bd172681.era1 +3a29dffbe1fdf5104ce49066c83e6f141c07e3d8d40ddf2d724223deb5b94c5e mainnet-01884-5732d988.era1 +c44e1614da6b9354732294c4e6615af19ca03bd4a6f967dcdffb36877e9be079 mainnet-01885-5480f074.era1 +6cb8e8d675993a2d48451afce0af65c0941fa3ccb10680bcbc52baa422c5f662 mainnet-01886-b5e8b2b0.era1 +c48f190c2b26d1cf9b8bf678cab4340faaf974c390eb4c4546399cc77fa242a4 mainnet-01887-dededef3.era1 +0c0bdea9087424b4a1fb4a6efbb5049fa814b1394f5ecffebc950d7ed08fc015 mainnet-01888-cdbce5e3.era1 +9a4d17719f76b51d6bd4be3a755be4bef91f43123a5e57982befc0aef35d5dde mainnet-01889-4a09fe43.era1 +426860d94b6b23be3d8ef680404107e9b55da28433bd514c93d5d4d41a5f6288 mainnet-01890-ff7a1b11.era1 +6c088ba4841eacd5c09a98b96631b48b655a79560cf81cfc7334af146e7e8d2a mainnet-01891-0f7bffdd.era1 +ee819214286025c3dd6f375a734a5f5b7f75567cc39f5dfda6eb3fd355a72e4b mainnet-01892-9671b1ed.era1 +f9fb6a102e845e4f7c3aab4ab72cac6720dc1a463cb541fdd24904430dcc320f mainnet-01893-1b07973b.era1 +ae91309834074d0b79557c499203bcfd03b6ddbad330874c68cb25780ca678cb mainnet-01894-80400894.era1 +30cad67a29a70185f0529bef58005ffc121fca1bfc02f95e4d7c00a4dd8aebba mainnet-01895-3f81607c.era1 +6f7cc262142969b3b06952cae4e0a2ff75710217beffd259a6128b60f2b8b23c mainnet-01896-e6ebe562.era1 diff --git a/internal/era/eradl/checksums_sepolia.txt b/internal/era/eradl/checksums_sepolia.txt new file mode 100644 index 0000000000..e8d6203999 --- /dev/null +++ b/internal/era/eradl/checksums_sepolia.txt @@ -0,0 +1,183 @@ +ab7f6d4f4eba0267406f783b75accc7a93dece520242d04fed27b0af51d79242 sepolia-00000-643a00f7.era1 +9cae627459d13ed3d05f6812eefa93242555fbefd27aa0927b40b62d44feb2e9 sepolia-00001-f3ea493e.era1 +a6f691585bc74fae6c445a8985f0df342e983ba1ef569018befb4b21b30891e2 sepolia-00002-dcb01f4d.era1 +1add5a98a9e6c15a667d6a7bbdaea115893019f3033664c54c2dcab70829268d sepolia-00003-18b32584.era1 +5e5ce2ca04b0f1aef6f026214cb64d16f76606fb5b5baf8a462f4a851dda0513 sepolia-00004-e93b3f11.era1 +db6f7687e9826a4e4dbc1361d666a8f2aa735eae309f63d9cadf6b27a899277b sepolia-00005-90918472.era1 +f61118a4e1cb718bdb71fde1daf84e59c3524b1e241ea1a5e2112d8c53acc625 sepolia-00006-a4a583b1.era1 +fd0c6fc443a4c30617ce88a48e7438fecaf4cf4772034511fa51433c7aae181a sepolia-00007-ef1e0a86.era1 +95bc416c6393e0a579f9e4af42421cf861e43354d49273d369bcf9b38e070246 sepolia-00008-dfe1e6dd.era1 +8262e7182f9a8abb9f5fc05d745a3cd2061eacda5c87cc2533af2407bd20672c sepolia-00009-dba60c04.era1 +d7c123c8e06713df23db0046df7c45d873e153ff076357b6d0c5bc9b0081a246 sepolia-00010-c99c706d.era1 +7fd359358ebf710c5c61a6a65551a4cb91c2160dbd7b59ed355a4d7e10f29328 sepolia-00011-04513853.era1 +9d6ea741d1b91e1c2c37ac1659ef3516d4968b6e7c164d347e534c4bebe644fd sepolia-00012-6e07302d.era1 +ce3e580fd3e5cb9e0ba9ebffae948406fdbe59f96fa3a05a30a381bc7d1b583e sepolia-00013-25709be2.era1 +15df46dc8c2cfd402f302f2925d1c50ac12538d394e8687920f53346429d6743 sepolia-00014-7c90e5a5.era1 +1985aaeb96c81279b978beab1145b3baf460b12bff86b8ca05c5067e1b0ca25b sepolia-00015-fadc08ab.era1 +2a53126cd443e9310fa15180c5bbbdb76f257d7fee67159500d8efa0ed13bef4 sepolia-00016-d44b2499.era1 +e783cff42ba7a53461c7fcdaf59a5387e7091a1230aa6761af05e7daf59b4805 sepolia-00017-02451eb3.era1 +92848afbeea81397fc9790e7fba7c627c01c17cbc5b8961a48ca60329bbfa3f3 sepolia-00018-cdb53b11.era1 +d15ac188a4dfac75818dfeb04e72c2f269d9f985100a457ebdc17661e36f0d83 sepolia-00019-fa770019.era1 +e8ef40780f55a0b640d1b68e1a89d1d438e8105bb1388bffc8a743b88e357671 sepolia-00020-15fc80e7.era1 +8041d790a0c50044e331a385eb98b17f5050ab25637b6a4f2c3e8e99f3f81e6e sepolia-00021-b8814b14.era1 +f17adda073b66cc97cb58acc7b776296e135943718dab9fc7cfecbac748419b7 sepolia-00022-87944c43.era1 +159a5ec4fa1e79be6d13fe4753eaa8994f547e31783069082a39d51e3e00b178 sepolia-00023-516a30f5.era1 +5b75090c9f26899aa6fe504963b7f1a43ab13a8fd7547da42f9ca9cc980511de sepolia-00024-b922dde6.era1 +d5c39668b309b43eec720b2185ac23ef819cc7fa92e35f2e6c9a4ce9ee1c249d sepolia-00025-a081e175.era1 +188b5119e110feec067dc06aefde7decba2a87bde642cc1735391a1782a99b03 sepolia-00026-d3931a12.era1 +3114068f4eb9cf8277d4417da371e820f0bf1a654600f8dea149f9854523d1f2 sepolia-00027-43f5e0ac.era1 +b18597daf66f27976638a84a4cac5622f7d53fca8264dac3665f84f28435cc26 sepolia-00028-dae08170.era1 +d0672ee04c5a84e881c4acc3757e16f963c57b5b69da81a674498c1b06159f3e sepolia-00029-17818143.era1 +122dff18aaac0bae0a006da088794f638ee95ddaa1e0a347ca9a8eca816471c1 sepolia-00030-cc7fc4eb.era1 +42c2206fda093c7aa6b31fad1addf2dd14e862b4686b0e17050bd284dc479cfd sepolia-00031-3171eede.era1 +42b023d07a02ad739b61ec8297c43501ddac200d1866fa3203df466d2442c4b0 sepolia-00032-9e2ff5ca.era1 +2461fb005a9a62cf6ab52a0b3505abde9828c1f36def4fa12a547ebb5e8c89c0 sepolia-00033-bc921023.era1 +2ca97708fba029693d7754a85424d29f57ee296a48fcbde02597603e7e90525d sepolia-00034-b2496634.era1 +d2944e1cbd7a3276ca5ef9d4b4473557a65e58bd512029b2fb00d41f618ac551 sepolia-00035-f3add4f1.era1 +c7f63d7230dd7ae9c57c33014d56bd4c921f5db95f3872bf6745d03bc64b5cc0 sepolia-00036-0db12924.era1 +dc027011c543418fcfdd7897cea3356de16122f676da2459d78da5369cdc2b8f sepolia-00037-ae8bdd13.era1 +9be2262ef4e1e1b93cee3316ad473895bd7a7f3bff15ac8c18c1a157292ab7f6 sepolia-00038-81f80b03.era1 +56c03c86028c95d431030fa2728493ca8001cc86eec3f5d7a558224e550b42ef sepolia-00039-03e5d6f1.era1 +d64e65ecfcf480c2edbdebac350ac899b25874a522c226695a46fab17de5b15c sepolia-00040-296fe287.era1 +18226ba389f150581b36a234d877fad9c08c0fa691a366ba11f808ec9110cf67 sepolia-00041-5cd87470.era1 +0d2960f23933deadcdfe545fc8aba626e79c0c010fad0ac01b577ca5b99840e0 sepolia-00042-de86936c.era1 +b14f66c2fc74d0f772eb75c548a86da4bf160cf1067091c65c05a90812e7af1f sepolia-00043-ede4e682.era1 +15d704883fadfcbe4ce3520bc9ed5fcff98a8a419b6fa9f832394008ae1941aa sepolia-00044-4d49a81a.era1 +5343d8015eb0a6b8728b571fd0e7a2bb92728ec593469b0a9d8d2082a5afc36d sepolia-00045-7071c19b.era1 +63efe606b8c687aeeff4d2ff5596a72da862d024f9dbb1ff5bf67ca4f2921f77 sepolia-00046-4f4fe79f.era1 +9eb6dd3772ebfe63c37a22423310a5cb36c0d09defd66d7aa02a5b4c1283ca80 sepolia-00047-76b58fb3.era1 +82afedad4e56f86d836446f0c71616f8d88fdec11b93a6360dacc111cdb12db2 sepolia-00048-0fa9d93c.era1 +8a86584323e83a11499265f33ddabe0de1517b51c8e73985fa6eed15cfd63d0b sepolia-00049-d193ff47.era1 +b66621a148fb7acce05efe6aab89be5a965463a4c4c95a3350e64f3e8a684417 sepolia-00050-736b969f.era1 +49d47547284339de6f92e6495347dce0c45c5294f07c1b96fcfa510c43cfc206 sepolia-00051-466eb482.era1 +b075750d6efdde0cd755c90cd893b2917c56ab8674022fb36bb7a1305dc9bfed sepolia-00052-9752212c.era1 +36eb486d7dab70e759c72198b9f2505ac3fcb7f6a0ae2cca82fd9ade3d65e86d sepolia-00053-b2897233.era1 +9f024ea4e135fe6939f2fedb6a6821d61202139fa35378616fcf0274bdeac172 sepolia-00054-aedad6a8.era1 +2bc46d10add9c9903d554523f6ed0c8f5a632521c659d9f3f4af4c444221d08c sepolia-00055-19af5091.era1 +21900526ff5f0f31257bdabaae3fffa700eccd3cf3a6ba346b4bdf4347c97324 sepolia-00056-9ac921a1.era1 +c9a47d7db6af1b984e6ad8de2ea0eb0e73e442281d4fa497ba64c02caaf0b7d0 sepolia-00057-240f011a.era1 +10d38d3b6b66367a1c05922040073d6a62a2cbb843ea821dbd02f4d9f037c740 sepolia-00058-06d606d6.era1 +d391f44dfa9bab3ced35676cd964daeffe0f4e4028c3bd44fe41010b761c5229 sepolia-00059-8ea69a55.era1 +39a1bdf4d7c1dd8365f635c8da568b34d1c2e59aa5d7fe8745d6b7db2cf2c6ed sepolia-00060-d22079b0.era1 +cf41ae65b6391d8c44bb0128e66591a96d42fea0a7d35c30c8eca5bbe0790578 sepolia-00061-834d00e3.era1 +9bcff9fa47c2addc140857b23d6453583ca526c6cdf11144583db24acf33b1b2 sepolia-00062-d1230cc2.era1 +984c5662f6f36ece4e0ca9efc47dcb3e50e0aa581a874a680736f2f558cdd889 sepolia-00063-e1e9fa40.era1 +7582532b67144ea9499c28d935e7ac4bbf8f465c382a8a97ce04e56539b8c9af sepolia-00064-7f827781.era1 +945e3da724660df934484d68868d54fbfaa5feaacdd635f6185b56e88858ad8d sepolia-00065-9d8993d6.era1 +77fdff04d6d6233c4bab9811ad559a328fdb0447070b96e2f38ea7450639a00e sepolia-00066-8d516260.era1 +3486301cf48b1f727b46c0223c4a018e03d0857efedc2f616ea850b539139f93 sepolia-00067-7466141b.era1 +2954560d2b1c6ff48242312b7f5fe902c53dc93a3d1c7d9abf41633926ef72ac sepolia-00068-1bd11e8a.era1 +8f27de663991d7e4e8a7005dee7b94f991cfefad743507362eca5ad83f53e449 sepolia-00069-536ecd2c.era1 +2d0fa324482aab3db61718abfb2a5c084a55db5f39c4bce125255eec9a56a01a sepolia-00070-b27f7c5c.era1 +472b1c9ec83d9b6564a45d4363c856604d21b53d8c89a7b5810f2596c14f710a sepolia-00071-d2ef5349.era1 +3a0e6051e4c5f1a263b51f7a827d2276c7b25cb9d426f24f39fca33a7e76d623 sepolia-00072-b23578a9.era1 +734b46f0bb7150e1d705bff53a0cdedd3ed57ca1461f06deb517c8b74c4b25c9 sepolia-00073-8bacb416.era1 +28091f1a78dc398e2d47212087f652c8d35f07cda5457ee691b4191c3a6698c8 sepolia-00074-0e81003c.era1 +b743e3e1721e593562d9a144f49a927bbe2db70be9e4884521cae9500b0004cb sepolia-00075-09177034.era1 +6850f49599b95dcf1db54a3c5d126654ca21de4df27b7a24bc35c4d10fe6cdb7 sepolia-00076-0f2898a3.era1 +da57f20ff5a3944bd1fef22e7c914f2eda3e79dd7346b0e7c0a01e69cf538d7e sepolia-00077-61de3538.era1 +fc20551b69bacce502fa42ba5b0a223c9fb558d5f495948e38c060328f1ceb7e sepolia-00078-be407b86.era1 +ab72961502e1d8055886d744c077dbf60db8acba64c7879109b3ed573ce4cd02 sepolia-00079-d5c957be.era1 +216b65dba90adf1288d40fc689f6087ff2435bd379df482b130cd464cbd1d490 sepolia-00080-ae6ce310.era1 +e824e04c1cf15f142bdbb40161b64953767abd3ec7c40a726ce69d4ce646df08 sepolia-00081-daac26d6.era1 +d70d059609dda26e25af96d32b646c364e2ae44fe7b1cf9e2e8589d731e9f381 sepolia-00082-ecb8f0c2.era1 +a7dc282ca7fd7aa8d42693363aec655d6cfea330220233c7aad3f7955284d650 sepolia-00083-5b017cd4.era1 +2f1006528caa6d47729c4ef0a699c441cb5d2c201afb6563ab51184429294020 sepolia-00084-8c1f92cd.era1 +374494754cfd728b1b4e4a00db810012346ba8c4dc9cf2ad1d80187999ab868b sepolia-00085-9180667c.era1 +7ff9b360a0656ddbace4032d249f5cf06068ee3f8be526d2a4ae0ed6eaef046f sepolia-00086-1aca7add.era1 +de592f4bde8de973d8c82a7d89dbe21cf75bb0b28204567ea4f5012b8be1f28c sepolia-00087-0e100944.era1 +fb6eb1e1e1ce97e03b39fe2d53e3595d759701a65cc861d0568c04ee7e2ec03c sepolia-00088-fcdd7aa5.era1 +4d178ce50f5436f5ba2347d87dc79e9a2e18c17d3056eb77c7c8dbb9b03bb986 sepolia-00089-b23b2368.era1 +21e919f0d32137e7924d54ddcf1e697bb5b57bbb7cc12a169475df993c4c1d9f sepolia-00090-b78edeb7.era1 +cb7ae025ca17c5f52ef7910147a47a0d3680c26f9d2d109d6af330f93f95b735 sepolia-00091-4c81cdca.era1 +1e0249554f150b63cb7dd57c53c624c197b415401c0a1f3986c2f06e8aaa795c sepolia-00092-ddbf3a4c.era1 +8d950d8c13a4e002514a47e6d6ebcad4bf7e5808398641a5c04863d9c90f0f87 sepolia-00093-a52a45ec.era1 +b8720324f04dca4e0046b12ec3b8a2b862158f3156c4d1fc2947340b1fc1a9cb sepolia-00094-839ea4e5.era1 +8c4134bbb21d36fbd7ba608eb1e485e76cb0fd56c4aa8032be1b6848757856d9 sepolia-00095-bccc0958.era1 +e3ad213e760ea2320ff52caf5de32ced37d6b7ad0f99384785ca42a7e58d1cd9 sepolia-00096-429b2f39.era1 +9c324e109f77ebc1750dd2a0941904ff820047def91f8b832e61c01b31297f38 sepolia-00097-6f74184d.era1 +26efc4469736b283fd80d9105fc85a70dbec209fbb0e1e40a905a9406e1bb3cc sepolia-00098-40286059.era1 +e14134b3aad0533366f9aeb19cf2561cf1e81b989a0b83f12b05493948dd71ea sepolia-00099-dd1ef4f4.era1 +7283a437244545e784d51186c0d7d4809808dd472850ca3cd2d7a40f4883b50d sepolia-00100-bd3d6bf4.era1 +b67270e94377703aac798d8323c0a91b451d36806775013a2b8b12db04797851 sepolia-00101-41676e0d.era1 +dd6ea805242a67c6255867f64fc5fbc941a98318b5ea1d5e2d42d42c6910493c sepolia-00102-4f3c1fe1.era1 +d6f6da94b16a201b304936cb5f798b6fedba76ead056cd2c4dc860c21d82b8dd sepolia-00103-e13a95f0.era1 +e2309561f7a86eddfe182dc86fb38e5454c5a272cc77b3d0d7c6ce987ddc874c sepolia-00104-4e49b068.era1 +deff905084758be35bf0b8cb640b1b283232abbc6153388a4275c767ea0bdf0e sepolia-00105-4ab7d9ea.era1 +964f9679a39fe06192a7025f14404cb1f6542071665f1c2f739f62fdb55e9274 sepolia-00106-5ec678af.era1 +8fd75370992f97e77a2cd3663bc1fb9b2bcec9b64a0439de7846d7c6321e6d93 sepolia-00107-44721c55.era1 +7e8219aa13d6a7b32c3a69888a2c5f446703eada3fdcde841ba26edfe3cb4453 sepolia-00108-3b4ad768.era1 +24e8d2f8d01abf63d97365bafa914dd5203f4e807bc6655dc0673b9f87215ebd sepolia-00109-16e54758.era1 +edadb0ebec6c4b7b54237e5802cc59fd962e23cf690ff10ab52c10258d7b7827 sepolia-00110-b5da103b.era1 +4faebfbdc009188cc8cf0ffe4aeca9c93ac5b3abe763cfb165d8bed37b12b51c sepolia-00111-15c53aba.era1 +40210479bd14ca3f8db76b288c2ed4e8f3d5b5ce8116ba8d8fe3133b0cc765ad sepolia-00112-8e2144e3.era1 +92ed406d564ed1504bc7ff91298a419fe72a710585256b1830040ba3d1adbde8 sepolia-00113-1e1aac0a.era1 +7e771bba1aa9c87be155a9a7d62d3479240f21934a3d763cafa5f3cd4ce49f8a sepolia-00114-0d7a4b23.era1 +51d71ed3674f5d70f719b3251e29a0825f2573b1bfd1a92940b013806aaf4fd3 sepolia-00115-8e983a59.era1 +6abea02d82f7a30b67d6de4516bbc711855eea3d891ea42fa0124c101f981f86 sepolia-00116-1708ba6e.era1 +88e7222e35b1275483b6eec11bf8d4417602fdb16b611d6c154abd8d0ec0b49a sepolia-00117-86962046.era1 +6ddeae324cc17337fa23c71b242ab1675b72f43fb393af7e971edec20451f864 sepolia-00118-934e9f5f.era1 +914c35142f7244d07b670b1f990c8bb5997119db451e8dcd8a67c8d71fcc6af2 sepolia-00119-4d88db3e.era1 +eedec437c182f330f2f5f3c530cce3bc59f0c99c9e6cd36288a588adba7679bb sepolia-00120-1a3274d5.era1 +4914f6a8cf63cb806c5736431f6402d9a99c2de953da05a17069fa15cf8c695b sepolia-00121-62b79757.era1 +b9a0138c77dcbb2b4784813204ec8bc30407cd8daf3501707719985acff4a1cb sepolia-00122-41d14652.era1 +57453e0eaa2bf46a13c94d9e96ee98943a46012c2bdd9da5d7c77064e803fbfd sepolia-00123-67f86708.era1 +1e927fdb13cebda45a963c8cec921b16c795fb3020cad9054fa1fb7f4cb528cd sepolia-00124-488cb226.era1 +8015846c8c3663005a8a6d59347fb672a602e6bbff028989355a01f5f6d2b183 sepolia-00125-8a21f7da.era1 +8807f6abe63b76f31d99cf14404fee8bb5eba3a814e2d08b9d85540ef9742550 sepolia-00126-6569478a.era1 +28dc46c8120426b395cf9b5ff781962a3212766b24511b2dc3d2172568b10021 sepolia-00127-1312ab23.era1 +ed66119ec9dae6c61952cbf40b9dc5770cd80e659a83dd18e1a5f2ffa947a04b sepolia-00128-1c95bdc6.era1 +a4a68dd54b77f21939ddb1ec9ef9ae0a3551d6d53b8f9578b01ad8e32e5c8d8e sepolia-00129-f32fdefa.era1 +e54d6d4b95a985f37391750b3bf3bc0f9f4e2f790805797ee198d77287433ca2 sepolia-00130-8f31c590.era1 +577fe68c5c33e47af8823ac573709ed9d63df0d7f9aec02a7907e3e6e5922d67 sepolia-00131-5aaad354.era1 +c3beada9620c55b6d0dbdab8f66b735da0b3d62d5c5eb2c3b5369619549fb3e0 sepolia-00132-2147d970.era1 +12843e128e76d5636f857c8c6801e433757fc4f8aba159bc2d4e6c41f2c94abd sepolia-00133-690cc16f.era1 +e5e4904ec83ebcebccc1aae1de89622a50bf6f735d985234da88fa1ced1787c0 sepolia-00134-fe276e6b.era1 +9c618458f6d76a09f16c86baf526dc7f2310ce92d862f73392144987c04b39ed sepolia-00135-ce40efd0.era1 +1d032d1279c3841c65385f85463226df04a98a3ccc5d7bf461f042492230615c sepolia-00136-adc6e1bb.era1 +a3aa401ca2bc8cb8b104667c6f68e28d00e37813a1a993d8abd1ec5c3555f71d sepolia-00137-805a333a.era1 +105c1e50e73715bf58d42f6bbe49bff36dc0051bfb477efc77ebf14b5ba98974 sepolia-00138-65ff170f.era1 +ad53fc0e4d2718ce105fa3a7ce5574dbb945f49b2fa7470a406179c45738fc46 sepolia-00139-1c86d86a.era1 +c27ae427ca0052686a3ac8a3e568d1dae30449f9edba465f218c147074d61ccc sepolia-00140-e7f36280.era1 +143d09ffb26cd2a1bb334958d92b77a92a8f9ac99c01059d22bee4e4d8bc3212 sepolia-00141-5d3d0d5a.era1 +378a77f0b0c4072297de4c382cece46be521a6c6935db8eb499dd99857d566aa sepolia-00142-e45aa418.era1 +35855d5bd75dff01248dd5b2080babf6127d87c157a987124f7a258cfb9a5ecb sepolia-00143-70379f59.era1 +58f07f98d8e9486acd01ec212518b1c0d7764e68263f9b1e9c51cf5e597a0b6b sepolia-00144-c345e75c.era1 +17caa603e2d1f9c01c9117754f0bb4c8ce42c58da806f758f99468d9f8c1c47b sepolia-00145-9f4bb4c5.era1 +d05a92b8fe1306397b98a6202b18f66c9bc259bd41c25b3d8211c09813e3a9ac sepolia-00146-3336d26b.era1 +b7120a656d06d4010a06a2abadd809ee7f26707cf313e9de5cb1bd172745ad23 sepolia-00147-6b007873.era1 +aa45cc5747e9c21ccfc44c87f98717702551a0511f423b2624a34af58ba798fc sepolia-00148-35f8a5b4.era1 +952843d531ea4d9ee9c456e50e77c50f75a559bff13326dd593271f90cd55129 sepolia-00149-01b6e9ca.era1 +2d93d1d84e0f4013d6daab61d66907488223a2f1b50e4a22d3ba1da24a9c6a84 sepolia-00150-0c372e80.era1 +6b516e3f31720c54453c5ce9bbac68300615f455a7cf4b1dc6592a5d5432ee89 sepolia-00151-c15a5955.era1 +82023cab017453e8fcf49ace9befbaef4af167e0e6c6976456bf251f803b5d51 sepolia-00152-ef7ac893.era1 +6ace677a17380127349ba0710fd02ff38ba185526cc2d9bbb6f05375d6f163f6 sepolia-00153-0e4073c2.era1 +66db5e0786cb9963ed66a0e31773b30d3405621a7636c62ffbb0b84ff41705bd sepolia-00154-298c3549.era1 +cf797283087a079773770c1bebfecb113a4155e0d77d5713c702478e2c24f64a sepolia-00155-a99309bb.era1 +b143cc994d0b544cd08b2a1f66308718ea49f3f68adef8e62300e91f8048130a sepolia-00156-8c33148f.era1 +cbc20f9f767324438a237c3114a1c4e65dda74d4a655d55a7cc3e63e62f373f8 sepolia-00157-ab02fc10.era1 +c8368d1752e66bcd7cabc653477f9aec0071027f91112a8cf71a945db23404e7 sepolia-00158-17992856.era1 +03a1a66eab3a7cbc63b29cfbe2e70285940e64db4af6d23ab70592c820f8d3ea sepolia-00159-b3448cf6.era1 +bf9dcd8400e56c58cd3280f0a3d7aab23a7eaf594e67db5387f40101ad8e8c92 sepolia-00160-acad7054.era1 +03a3b975b2a78a4b28afd9ee089440465ceefd32bd1d82b74ae69caa80b6fb6c sepolia-00161-36e611bd.era1 +ddf201b59ebc77eccdec97b0a5a7d7a89dda02928ff7c5cca8868b5aba84f533 sepolia-00162-3557cc58.era1 +041be469daf6f7abaa0cfe66c4d68b7d9d223383553c16f078edb3a1fa3d0d92 sepolia-00163-638b9afe.era1 +68d151048412318cbd0af98efa27d7ee16e2fc58830d93b4d76b66cb632ebfc3 sepolia-00164-fbc67b64.era1 +3025771380736a5de790ead991c0512a4c73106fd1d2f169863d395964238ac1 sepolia-00165-442b83a1.era1 +6d6b1273a6fc353c6999b4c9be301660a404b78cced911e230991305da990e3c sepolia-00166-018915fc.era1 +01052c4f779e4ec276498d4192b8ad11ad6d2d3992224bb62ea882a80deda935 sepolia-00167-0df2b4c5.era1 +2f8f3034eb7e41c5add0e639e21b52c0794f36bb5918274849402c5fe0d247e6 sepolia-00168-7cab66f5.era1 +504b0203d995e5ef6aee679b048c276f45b05dc68a6fd319a0f4f0133b230a77 sepolia-00169-75850131.era1 +b277df79fe5a83189f9619b275a9aaab63db8506539c56997be61fd5a3552bb9 sepolia-00170-c2044b78.era1 +1af0a1778fc5d2a53aaca06dbda6671b91ae3f56da73a6c6708bc729e5fb9efd sepolia-00171-af44ff2e.era1 +a977654c0ed243ccce7b5514914ec94d70a3a742ff014ac52b0654e21940f2da sepolia-00172-bd76a8d9.era1 +146672b2e63c320c9474ecf41d7f32f31f5298512cc8f911074c88789849d935 sepolia-00173-b6924da5.era1 +82af1c5bc51f9e9ae1be5d0e0827ea755d104ed373b374c08ef401115491671f sepolia-00174-2a61fac5.era1 +627ee6cf9282191ff32d291fc0437b812bad01f158b5ca42ae717b7bbb125f8c sepolia-00175-1cc76405.era1 +6ee38f117646a47f6ab2f666fa6460bda770c194ae4a29744534e9bfd9e7ba3b sepolia-00176-20daa2c6.era1 +28e7e49e71dd8581cc484d8be89fb083a79577b06f26c1e3bfd4a57bdf24c5e7 sepolia-00177-379df7e4.era1 +055c365cfeda3495a5e2b334803dfffe7af2a584745acabc42b5ad146b250534 sepolia-00178-88c9d2aa.era1 +bca9a920232983636b7cf20fc8319f891df94ba0860f51b5a052290b58d9e3ae sepolia-00179-8329b80c.era1 +e894a6f3ce0ede2825aaafa64122a5f458cd3b2ecaeae20a44a59fd668971bb0 sepolia-00180-22de0418.era1 +83bfe0d7c49c3a108a4ed044119a3549f2f4b0f8e74c971150b6977b7d46a250 sepolia-00181-b3fbe6f2.era1 +3b806177536ac3615f376440c0589696ea746eea0215bb3b175df8f4f1e73894 sepolia-00182-a4f0a8a1.era1 diff --git a/internal/era/eradl/eradl.go b/internal/era/eradl/eradl.go new file mode 100644 index 0000000000..30bd2bc0d5 --- /dev/null +++ b/internal/era/eradl/eradl.go @@ -0,0 +1,115 @@ +// Copyright 2025 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 . + +// Package eradl implements downloading of era1 files. +package eradl + +import ( + _ "embed" + "fmt" + "net/url" + "path/filepath" + "regexp" + "strconv" + + "github.com/ethereum/go-ethereum/internal/download" + "github.com/ethereum/go-ethereum/internal/era" +) + +//go:embed checksums_mainnet.txt +var mainnetDB []byte + +//go:embed checksums_sepolia.txt +var sepoliaDB []byte + +type Loader struct { + csdb *download.ChecksumDB + network string + baseURL *url.URL +} + +// New creates an era1 loader for the given server URL and network name. +func New(baseURL string, network string) (*Loader, error) { + var checksums []byte + switch network { + case "mainnet": + checksums = mainnetDB + case "sepolia": + checksums = sepoliaDB + default: + return nil, fmt.Errorf("missing era1 checksum definitions for network %q", network) + } + + csdb, err := download.ParseChecksums(checksums) + if err != nil { + return nil, fmt.Errorf("invalid checksums: %v", err) + } + + base, err := url.Parse(baseURL) + if err != nil { + return nil, fmt.Errorf("invalid base URL %q: %v", baseURL, err) + } + if base.Scheme != "http" && base.Scheme != "https" { + return nil, fmt.Errorf("invalid base URL scheme, expected http(s): %q", baseURL) + } + + l := &Loader{ + network: network, + csdb: csdb, + baseURL: base, + } + return l, nil +} + +// DownloadAll downloads all known era1 files to the given directory. +func (l *Loader) DownloadAll(destDir string) error { + for file := range l.csdb.Files() { + if err := l.download(file, destDir); err != nil { + return err + } + } + return nil +} + +// DownloadBlockRange fetches the era1 files for the given block range. +func (l *Loader) DownloadBlockRange(start, end uint64, destDir string) error { + startEpoch := start / uint64(era.MaxEra1Size) + endEpoch := end / uint64(era.MaxEra1Size) + return l.DownloadEpochRange(startEpoch, endEpoch, destDir) +} + +// DownloadEpochRange fetches the era1 files in the given epoch range. +func (l *Loader) DownloadEpochRange(start, end uint64, destDir string) error { + pat := regexp.MustCompile(regexp.QuoteMeta(l.network) + "-([0-9]+)-[0-9a-f]+\\.era1") + for file := range l.csdb.Files() { + m := pat.FindStringSubmatch(file) + if len(m) == 2 { + fileEpoch, _ := strconv.Atoi(m[1]) + if uint64(fileEpoch) >= start && uint64(fileEpoch) <= end { + if err := l.download(file, destDir); err != nil { + return err + } + } + } + } + return nil +} + +func (l *Loader) download(file, destDir string) error { + url := l.baseURL.JoinPath(file).String() + dest := filepath.Join(destDir, file) + return l.csdb.DownloadFile(url, dest) +} From 1f175347c47810564c7d6fab3bbd855eb449468d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Kj=C3=A6rstad?= Date: Thu, 15 May 2025 22:54:18 +0200 Subject: [PATCH 027/365] build: upgrade -dlgo version to Go 1.24.3 (#31774) New security fix: https://groups.google.com/g/golang-announce/c/UZoIkUT367A --- build/checksums.txt | 94 ++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/build/checksums.txt b/build/checksums.txt index a914d79860..c819429969 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -5,54 +5,54 @@ # https://github.com/ethereum/execution-spec-tests/releases/download/pectra-devnet-6%40v1.0.0/ b69211752a3029083c020dc635fe12156ca1a6725a08559da540a0337586a77e fixtures_pectra-devnet-6.tar.gz -# version:golang 1.24.2 +# version:golang 1.24.3 # https://go.dev/dl/ -9dc77ffadc16d837a1bf32d99c624cb4df0647cee7b119edd9e7b1bcc05f2e00 go1.24.2.src.tar.gz -427b373540d8fd51dbcc46bdecd340af109cd41514443c000d3dcde72b2c65a3 go1.24.2.aix-ppc64.tar.gz -238d9c065d09ff6af229d2e3b8b5e85e688318d69f4006fb85a96e41c216ea83 go1.24.2.darwin-amd64.tar.gz -535ed9ff283fee39575a7fb9b6d8b1901b6dc640d06dc71fd7d3faeefdaf8030 go1.24.2.darwin-amd64.pkg -b70f8b3c5b4ccb0ad4ffa5ee91cd38075df20fdbd953a1daedd47f50fbcff47a go1.24.2.darwin-arm64.tar.gz -4732f607a47ce4d898c0af01ff68f07e0820a6b50603aef5d5c777d1102505e2 go1.24.2.darwin-arm64.pkg -c17686b5fd61a663fbfafccfa177961be59386cf294e935ce35866b9dcb8e78a go1.24.2.dragonfly-amd64.tar.gz -026f1dd906189acff714c7625686bbc4ed91042618ba010d45b671461acc9e63 go1.24.2.freebsd-386.tar.gz -49399ba759b570a8f87d12179133403da6c2dd296d63a8830dee309161b9c40c go1.24.2.freebsd-amd64.tar.gz -1f48f47183794d97c29736004247ab541177cf984ac6322c78bc43828daa1172 go1.24.2.freebsd-arm.tar.gz -ef856428b60a8c0bd9a2cba596e83024be6f1c2d5574e89cb1ff2262b08df8b9 go1.24.2.freebsd-arm64.tar.gz -ec2088823e16df00600a6d0f72e9a7dc6d2f80c9c140c2043c0cf20e1404d1a9 go1.24.2.freebsd-riscv64.tar.gz -e030e7cedbb8688f1d75cb80f3de6ee2e6617a67d34051e794e5992b53462147 go1.24.2.illumos-amd64.tar.gz -4c382776d52313266f3026236297a224a6688751256a2dffa3f524d8d6f6c0ba go1.24.2.linux-386.tar.gz -68097bd680839cbc9d464a0edce4f7c333975e27a90246890e9f1078c7e702ad go1.24.2.linux-amd64.tar.gz -756274ea4b68fa5535eb9fe2559889287d725a8da63c6aae4d5f23778c229f4b go1.24.2.linux-arm64.tar.gz -438d5d3d7dcb239b58d893a715672eabe670b9730b1fd1c8fc858a46722a598a go1.24.2.linux-armv6l.tar.gz -6aefd3bf59c3c5592eda4fb287322207f119c2210f3795afa9be48d3ccb73e1b go1.24.2.linux-loong64.tar.gz -93e49bb4692783b0e9a2deab9558c6e8d2867f35592aeff285adda60924167f3 go1.24.2.linux-mips.tar.gz -6e86e703675016f3faf6604b8f68f20dc1bba75849136e6dd4f43f69c8a4a9d9 go1.24.2.linux-mips64.tar.gz -f233d237538ca1559a7d7cf519a29f0147923a951377bc4e467af4c059e68851 go1.24.2.linux-mips64le.tar.gz -545e1b9a7939f923fd53bde98334b987ef42eb353ee3e0bfede8aa06079d6b24 go1.24.2.linux-mipsle.tar.gz -6eab31481f2f46187bc1b6c887662eef06fc9d7271a8390854072cdb387c8d74 go1.24.2.linux-ppc64.tar.gz -5fff857791d541c71d8ea0171c73f6f99770d15ff7e2ad979104856d01f36563 go1.24.2.linux-ppc64le.tar.gz -91bda1558fcbd1c92769ad86c8f5cf796f8c67b0d9d9c19f76eecfc75ce71527 go1.24.2.linux-riscv64.tar.gz -1cb3448166d6abb515a85a3ee5afbdf932081fb58ad7143a8fb666fbc06146d9 go1.24.2.linux-s390x.tar.gz -a9a2c0db2e826f20f00b02bee01dfdaeb49591c2f6ffacb78dc64a950894f7ff go1.24.2.netbsd-386.tar.gz -cd1a35b76ed9c7b6c0c1616741bd319699a77867ade0be9924f32496c0a87a3f go1.24.2.netbsd-amd64.tar.gz -8c666388d066e479155cc5116950eeb435df28087ef277c18f1dc7479f836e60 go1.24.2.netbsd-arm.tar.gz -5d42f0be04f58da5be788a1e260f8747c316b8ce182bf0b273c2e4c691feaa1a go1.24.2.netbsd-arm64.tar.gz -688effa23ea3973cc8b0fdf4246712cbeef55ff20c45f3a9e28b0c2db04246cf go1.24.2.openbsd-386.tar.gz -e5daf95f1048d8026b1366450a3f8044d668b0639db6422ad9a83755c6745cf7 go1.24.2.openbsd-amd64.tar.gz -aeadaf74bd544d1a12ba9b14c0e7cdb1964de3ba9a52acb4619e91dbae7def7b go1.24.2.openbsd-arm.tar.gz -9e222d9adb0ce836a5b3c8d5aadbd167c8869c030b113f4a81aa88e9a200f279 go1.24.2.openbsd-arm64.tar.gz -192fffa34536adc3cd1bb7c1ee785b8bc156ae7afd10bbf5db99ec8f2e93066e go1.24.2.openbsd-ppc64.tar.gz -a23e90b451a390549042c2a7efbec6f29ed98b2d5618c8d2a35704e21be96e09 go1.24.2.openbsd-riscv64.tar.gz -5cdcafe455d859b02779611a5a1e1d63e498b922e05818fb3debe410a5959e9e go1.24.2.plan9-386.tar.gz -81351659804fa505c1b3ec6fdf9599f7f88df08614307eeb96071bf5e2e74beb go1.24.2.plan9-amd64.tar.gz -6e337d5def14ed0123423c1c32e2e6d8b19161e5d5ffaa7356dad48ee0fd80b4 go1.24.2.plan9-arm.tar.gz -07e6926ebc476c044d7d5b17706abfc52be52bccc2073d1734174efe63c6b35e go1.24.2.solaris-amd64.tar.gz -13d86cb818bba331da75fcd18246ab31a1067b44fb4a243b6dfd93097eda7f37 go1.24.2.windows-386.zip -8a702d9f7104a15bd935f4191c58c24c0b6389e066b9d5661b93915114a2bef0 go1.24.2.windows-386.msi -29c553aabee0743e2ffa3e9fa0cda00ef3b3cc4ff0bc92007f31f80fd69892e1 go1.24.2.windows-amd64.zip -acefb191e72fea0bdb1a3f5f8f6f5ab18b42b3bbce0c7183f189f25953aff275 go1.24.2.windows-amd64.msi -ab267f7f9a3366d48d7664be9e627ce3e63273231430cce5f7783fb910f14148 go1.24.2.windows-arm64.zip -d187bfe539356c39573d2f46766d1d08122b4f33da00fd14d12485fa9e241ff5 go1.24.2.windows-arm64.msi +229c08b600b1446798109fae1f569228102c8473caba8104b6418cb5bc032878 go1.24.3.src.tar.gz +6f6901497547db3b77c14f7f953fbcef9fa5fb84199ee2ee14a5686e66bed5a6 go1.24.3.aix-ppc64.tar.gz +a05fa7e4043a4fec66897135219e3b8ab2202b5ef351c60c2fbb531dfb8f2900 go1.24.3.darwin-amd64.pkg +13e6fe3fcf65689d77d40e633de1e31c6febbdbcb846eb05fc2434ed2213e92b go1.24.3.darwin-amd64.tar.gz +97055ff4214043b39dc32e043fdd5c565df7c0a4e2fc0174e779a134c347ae0e go1.24.3.darwin-arm64.pkg +64a3fa22142f627e78fac3018ce3d4aeace68b743eff0afda8aae0411df5e4fb go1.24.3.darwin-arm64.tar.gz +32de3fd44d5055973978436a7f1f0ffbaae85c1b603ec6105e5c38d8a674c721 go1.24.3.dragonfly-amd64.tar.gz +9fe6101b3797919bd7337ee5ce591954f85d59db7ae88983904db29fd64c3dd1 go1.24.3.freebsd-386.tar.gz +6ccf4cca287e90cc28cd7954b6172f5d177a17e20b072b65f7f39636c325e2fb go1.24.3.freebsd-amd64.tar.gz +ce45ebf389066f82a7b056b66dd650efb51fde6f8bf92a2a3ab6990f02788ebf go1.24.3.freebsd-arm.tar.gz +8f6494a12a874d0ea57c67987829359e016960ce3ba0673273609d6ac2af589a go1.24.3.freebsd-arm64.tar.gz +f9db392560cf0851f0bc8f2190e1978e01b4603038c27fecfc8658a695b71616 go1.24.3.freebsd-riscv64.tar.gz +01717fff64c5d98457272002fa825d0a15e307bf6e189f2b0c23817fa033b61c go1.24.3.illumos-amd64.tar.gz +41b1051063e68cbd2b919bf12326764fe33937cf1d32b5c529dd1a4f43dce578 go1.24.3.linux-386.tar.gz +3333f6ea53afa971e9078895eaa4ac7204a8c6b5c68c10e6bc9a33e8e391bdd8 go1.24.3.linux-amd64.tar.gz +a463cb59382bd7ae7d8f4c68846e73c4d589f223c589ac76871b66811ded7836 go1.24.3.linux-arm64.tar.gz +17a392d7e826625dd12a32099df0b00b85c32d8132ed86fe917183ee5c3f88ed go1.24.3.linux-armv6l.tar.gz +e4b003c04c902edc140153d279b42167f1ad7c229f48f1f729bbef5e65e88d1f go1.24.3.linux-loong64.tar.gz +1c79d89edf835edf9d4336ccea7cb89bc5c0ca82b12b36b218d599a5400d60fe go1.24.3.linux-mips.tar.gz +0b64fe147d69f4d681d8e8a035c760477531432f83d831f18d37cb9bf3652488 go1.24.3.linux-mips64.tar.gz +396b784c255b64512dc00c302c053e43a3cbfc77518664c6ac5569aafad4d1e6 go1.24.3.linux-mips64le.tar.gz +93898313887f14e8efbe9d7386d5da4792b2d6c492bee562993fd4c9daa75c6d go1.24.3.linux-mipsle.tar.gz +873ae3a6a6655a7b6f820e095d9965507e8dfd3cf76bc92d75c564ecbca385f6 go1.24.3.linux-ppc64.tar.gz +341a749d168f47b1d4dad25e32cae70849b7ceed7c290823b853c9e6b0df0856 go1.24.3.linux-ppc64le.tar.gz +fa482f53ccb4ba280316b8c5751ea67291507280d9166f2a38fe4d9b5d5fb64b go1.24.3.linux-riscv64.tar.gz +a87b0c2a079a0bece1620fb29a00e02b4dba17507850f837e754af7d57cda282 go1.24.3.linux-s390x.tar.gz +63155382308db1306200aff7821aa26bf2a2dda23537dd637a9704b485b6ddf0 go1.24.3.netbsd-386.tar.gz +fe2c5c79482958b867c08a4fc2a10a998de9c0206b08d5b3ebcb2232e8d2777c go1.24.3.netbsd-amd64.tar.gz +e8ff77aef21521b5dd94e44282a3243309b80717414cf12f72835a45886a049f go1.24.3.netbsd-arm.tar.gz +b337fbaf82822685940ffaa76fbcf4be5d2f0258bc819cd80bc408b491f45c04 go1.24.3.netbsd-arm64.tar.gz +c1bb9dd8418480aa7f65452b08de3759da3bf89702be71b5a9fc084836b24ad5 go1.24.3.openbsd-386.tar.gz +531218de748b0caaf6d1ad18921206fc12baaa89bf483a0a5e60a571c206fe6f go1.24.3.openbsd-amd64.tar.gz +bcd0dc959986fc346969b5d4111c3c8031882d8bf8d87a2c2ecf1328962a91f2 go1.24.3.openbsd-arm.tar.gz +00ee6f8f1c41fd2e28ad386bd7e39acce7cab84af6de835855b29d1c597335c4 go1.24.3.openbsd-arm64.tar.gz +9f4ec0a9203ed3c54ce1a2a390ad3d45838cdb7efd85baeff857e37dfde04edd go1.24.3.openbsd-ppc64.tar.gz +da4d6f80e2373250d8c31c32dcd1e08775c327c0d610923604660cc0e07e8cba go1.24.3.openbsd-riscv64.tar.gz +f5d02149132eedda6c2d46b360d7da462b8a5f9e3f8567db100c2d7bff0ddcd7 go1.24.3.plan9-386.tar.gz +175f3d79f4762a3c545d2c6393bf6b8bac24e838026869dafab06b930735c94f go1.24.3.plan9-amd64.tar.gz +d1e4ac15095da1611659261c2228c2058756cf87d61d9fad262f76755ef26849 go1.24.3.plan9-arm.tar.gz +e644220a6ced3c07a7acc1364193cb709a97737dd8b6792a07a8ec6d9996713e go1.24.3.solaris-amd64.tar.gz +0d7e7dc0a31ba0cdd487415709d03b02fc9490ef111e8dfd22788a6d63316f37 go1.24.3.windows-386.msi +c27c463a61ab849266baa0c17a6c5c4256a574ab642f609ba25c96ec965dc184 go1.24.3.windows-386.zip +d5b7637e7e138be877d96a4501709d480e050d86a8f402bc950e72112b5aedc5 go1.24.3.windows-amd64.msi +be9787cb08998b1860fe3513e48a5fe5b96302d358a321b58e651184fa9638b3 go1.24.3.windows-amd64.zip +7efde2e5e8468e9caf2c7fc94f4da78a726a5031a1ed63acff7899527cdddff6 go1.24.3.windows-arm64.msi +eec9fa736056b54dd88ecb669db2bfad39b0c48f6f9080f036dfa1ca42dc4bb5 go1.24.3.windows-arm64.zip # version:golangci 2.0.2 # https://github.com/golangci/golangci-lint/releases/ From 57e985ecabf567f9a752e1e3ed56533f63787d0e Mon Sep 17 00:00:00 2001 From: Sina M <1591639+s1na@users.noreply.github.com> Date: Fri, 16 May 2025 10:20:36 +0200 Subject: [PATCH 028/365] cmd/utils: remove deprecated LES flags (#31838) They were not widely used in users setups. --- cmd/geth/main.go | 6 ------ cmd/utils/flags.go | 23 ----------------------- cmd/utils/flags_legacy.go | 37 ------------------------------------- 3 files changed, 66 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index bdff96e369..733c9cf230 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -91,13 +91,7 @@ var ( utils.LogNoHistoryFlag, utils.LogExportCheckpointsFlag, utils.StateHistoryFlag, - utils.LightServeFlag, // deprecated - utils.LightIngressFlag, // deprecated - utils.LightEgressFlag, // deprecated - utils.LightMaxPeersFlag, // deprecated - utils.LightNoPruneFlag, // deprecated utils.LightKDFFlag, - utils.LightNoSyncServeFlag, // deprecated utils.EthRequiredBlocksFlag, utils.LegacyWhitelistFlag, // deprecated utils.CacheFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a100ee1548..169f5ed49e 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1245,28 +1245,6 @@ func setIPC(ctx *cli.Context, cfg *node.Config) { } } -// setLes shows the deprecation warnings for LES flags. -func setLes(ctx *cli.Context, cfg *ethconfig.Config) { - if ctx.IsSet(LightServeFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightServeFlag.Name) - } - if ctx.IsSet(LightIngressFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightIngressFlag.Name) - } - if ctx.IsSet(LightEgressFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightEgressFlag.Name) - } - if ctx.IsSet(LightMaxPeersFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightMaxPeersFlag.Name) - } - if ctx.IsSet(LightNoPruneFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoPruneFlag.Name) - } - if ctx.IsSet(LightNoSyncServeFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoSyncServeFlag.Name) - } -} - // MakeDatabaseHandles raises out the number of allowed file handles per process // for Geth and returns half of the allowance to assign to the database. func MakeDatabaseHandles(max int) int { @@ -1582,7 +1560,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { setBlobPool(ctx, &cfg.BlobPool) setMiner(ctx, &cfg.Miner) setRequiredBlocks(ctx, cfg) - setLes(ctx, cfg) // Cap the cache allowance and tune the garbage collector mem, err := gopsutil.VirtualMemory() diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index ff63dd5685..dc41a75d11 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -39,12 +39,6 @@ var DeprecatedFlags = []cli.Flag{ CacheTrieRejournalFlag, LegacyDiscoveryV5Flag, TxLookupLimitFlag, - LightServeFlag, - LightIngressFlag, - LightEgressFlag, - LightMaxPeersFlag, - LightNoPruneFlag, - LightNoSyncServeFlag, LogBacktraceAtFlag, LogDebugFlag, MinerNewPayloadTimeoutFlag, @@ -88,37 +82,6 @@ var ( Value: ethconfig.Defaults.TransactionHistory, Category: flags.DeprecatedCategory, } - // Light server and client settings, Deprecated November 2023 - LightServeFlag = &cli.IntFlag{ - Name: "light.serve", - Usage: "Maximum percentage of time allowed for serving LES requests (deprecated)", - Category: flags.DeprecatedCategory, - } - LightIngressFlag = &cli.IntFlag{ - Name: "light.ingress", - Usage: "Incoming bandwidth limit for serving light clients (deprecated)", - Category: flags.DeprecatedCategory, - } - LightEgressFlag = &cli.IntFlag{ - Name: "light.egress", - Usage: "Outgoing bandwidth limit for serving light clients (deprecated)", - Category: flags.DeprecatedCategory, - } - LightMaxPeersFlag = &cli.IntFlag{ - Name: "light.maxpeers", - Usage: "Maximum number of light clients to serve, or light servers to attach to (deprecated)", - Category: flags.DeprecatedCategory, - } - LightNoPruneFlag = &cli.BoolFlag{ - Name: "light.nopruning", - Usage: "Disable ancient light chain data pruning (deprecated)", - Category: flags.DeprecatedCategory, - } - LightNoSyncServeFlag = &cli.BoolFlag{ - Name: "light.nosyncserve", - Usage: "Enables serving light clients before syncing (deprecated)", - Category: flags.DeprecatedCategory, - } // Deprecated November 2023 LogBacktraceAtFlag = &cli.StringFlag{ Name: "log.backtrace", From 892a661ee2e7bcafcfd4eb981abf0ba697d57a5c Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Fri, 16 May 2025 18:29:38 +0800 Subject: [PATCH 029/365] core, triedb/pathdb: final integration (snapshot integration pt 5) (#30661) In this pull request, snapshot generation in pathdb has been ported from the legacy state snapshot implementation. Additionally, when running in path mode, legacy state snapshot data is now managed by the pathdb based snapshot logic. Note: Existing snapshot data will be re-generated, regardless of whether it was previously fully constructed. --- core/blockchain.go | 62 +- core/blockchain_repair_test.go | 34 +- core/blockchain_sethead_test.go | 2 +- core/blockchain_snapshot_test.go | 22 +- core/state/database.go | 25 +- core/state/snapshot/generate_test.go | 4 +- core/state/statedb_test.go | 3 +- eth/handler.go | 3 +- eth/protocols/snap/handler.go | 44 +- eth/protocols/snap/sync_test.go | 2 +- tests/block_test_util.go | 6 +- trie/database_test.go | 6 +- triedb/database.go | 20 + triedb/pathdb/buffer.go | 10 +- triedb/pathdb/context.go | 246 ++++++++ triedb/pathdb/database.go | 138 ++++- triedb/pathdb/database_test.go | 3 +- triedb/pathdb/disklayer.go | 205 ++++++- triedb/pathdb/errors.go | 9 + triedb/pathdb/flush.go | 68 +++ triedb/pathdb/generate.go | 856 +++++++++++++++++++++++++++ triedb/pathdb/generate_test.go | 766 ++++++++++++++++++++++++ triedb/pathdb/iterator.go | 18 +- triedb/pathdb/iterator_binary.go | 36 +- triedb/pathdb/iterator_fast.go | 25 +- triedb/pathdb/iterator_test.go | 217 +++---- triedb/pathdb/journal.go | 59 +- triedb/pathdb/metrics.go | 51 +- triedb/pathdb/states.go | 9 +- 29 files changed, 2701 insertions(+), 248 deletions(-) create mode 100644 triedb/pathdb/context.go create mode 100644 triedb/pathdb/generate.go create mode 100644 triedb/pathdb/generate_test.go diff --git a/core/blockchain.go b/core/blockchain.go index 320b90dcbe..f93cddfe44 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -183,8 +183,13 @@ func (c *CacheConfig) triedbConfig(isVerkle bool) *triedb.Config { } if c.StateScheme == rawdb.PathScheme { config.PathDB = &pathdb.Config{ - StateHistory: c.StateHistory, - CleanCacheSize: c.TrieCleanLimit * 1024 * 1024, + StateHistory: c.StateHistory, + TrieCleanSize: c.TrieCleanLimit * 1024 * 1024, + StateCleanSize: c.SnapshotLimit * 1024 * 1024, + + // TODO(rjl493456442): The write buffer represents the memory limit used + // for flushing both trie data and state data to disk. The config name + // should be updated to eliminate the confusion. WriteBufferSize: c.TrieDirtyLimit * 1024 * 1024, } } @@ -380,11 +385,14 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // Do nothing here until the state syncer picks it up. log.Info("Genesis state is missing, wait state sync") } else { - // Head state is missing, before the state recovery, find out the - // disk layer point of snapshot(if it's enabled). Make sure the - // rewound point is lower than disk layer. + // Head state is missing, before the state recovery, find out the disk + // layer point of snapshot(if it's enabled). Make sure the rewound point + // is lower than disk layer. + // + // Note it's unnecessary in path mode which always keep trie data and + // state data consistent. var diskRoot common.Hash - if bc.cacheConfig.SnapshotLimit > 0 { + if bc.cacheConfig.SnapshotLimit > 0 && bc.cacheConfig.StateScheme == rawdb.HashScheme { diskRoot = rawdb.ReadSnapshotRoot(bc.db) } if diskRoot != (common.Hash{}) { @@ -457,7 +465,32 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis bc.logger.OnGenesisBlock(bc.genesisBlock, alloc) } } + bc.setupSnapshot() + + // Rewind the chain in case of an incompatible config upgrade. + if compatErr != nil { + log.Warn("Rewinding chain to upgrade configuration", "err", compatErr) + if compatErr.RewindToTime > 0 { + bc.SetHeadWithTimestamp(compatErr.RewindToTime) + } else { + bc.SetHead(compatErr.RewindToBlock) + } + rawdb.WriteChainConfig(db, genesisHash, chainConfig) + } + + // Start tx indexer if it's enabled. + if txLookupLimit != nil { + bc.txIndexer = newTxIndexer(*txLookupLimit, bc) + } + return bc, nil +} +func (bc *BlockChain) setupSnapshot() { + // Short circuit if the chain is established with path scheme, as the + // state snapshot has been integrated into path database natively. + if bc.cacheConfig.StateScheme == rawdb.PathScheme { + return + } // Load any existing snapshot, regenerating it if loading failed if bc.cacheConfig.SnapshotLimit > 0 { // If the chain was rewound past the snapshot persistent layer (causing @@ -465,7 +498,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // in recovery mode and in that case, don't invalidate the snapshot on a // head mismatch. var recover bool - head := bc.CurrentBlock() if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer >= head.Number.Uint64() { log.Warn("Enabling snapshot recovery", "chainhead", head.Number, "diskbase", *layer) @@ -482,22 +514,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // Re-initialize the state database with snapshot bc.statedb = state.NewDatabase(bc.triedb, bc.snaps) } - - // Rewind the chain in case of an incompatible config upgrade. - if compatErr != nil { - log.Warn("Rewinding chain to upgrade configuration", "err", compatErr) - if compatErr.RewindToTime > 0 { - bc.SetHeadWithTimestamp(compatErr.RewindToTime) - } else { - bc.SetHead(compatErr.RewindToBlock) - } - rawdb.WriteChainConfig(db, genesisHash, chainConfig) - } - // Start tx indexer if it's enabled. - if txLookupLimit != nil { - bc.txIndexer = newTxIndexer(*txLookupLimit, bc) - } - return bc, nil } // empty returns an indicator whether the blockchain is empty. diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 6c52d057ad..edc8854892 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -1791,7 +1791,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s } ) defer engine.Close() - if snapshots { + if snapshots && scheme == rawdb.HashScheme { config.SnapshotLimit = 256 config.SnapshotWait = true } @@ -1820,7 +1820,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil { t.Fatalf("Failed to flush trie state: %v", err) } - if snapshots { + if snapshots && scheme == rawdb.HashScheme { if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { t.Fatalf("Failed to flatten snapshots: %v", err) } @@ -1952,8 +1952,10 @@ func testIssue23496(t *testing.T, scheme string) { if _, err := chain.InsertChain(blocks[1:2]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } - if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil { - t.Fatalf("Failed to flatten snapshots: %v", err) + if scheme == rawdb.HashScheme { + if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil { + t.Fatalf("Failed to flatten snapshots: %v", err) + } } // Insert block B3 and commit the state into disk @@ -1997,15 +1999,23 @@ func testIssue23496(t *testing.T, scheme string) { } expHead := uint64(1) if scheme == rawdb.PathScheme { - expHead = uint64(2) + // The pathdb database makes sure that snapshot and trie are consistent, + // so only the last block is reverted in case of a crash. + expHead = uint64(3) } if head := chain.CurrentBlock(); head.Number.Uint64() != expHead { t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead) } - - // Reinsert B2-B4 - if _, err := chain.InsertChain(blocks[1:]); err != nil { - t.Fatalf("Failed to import canonical chain tail: %v", err) + if scheme == rawdb.PathScheme { + // Reinsert B4 + if _, err := chain.InsertChain(blocks[3:]); err != nil { + t.Fatalf("Failed to import canonical chain tail: %v", err) + } + } else { + // Reinsert B2-B4 + if _, err := chain.InsertChain(blocks[1:]); err != nil { + t.Fatalf("Failed to import canonical chain tail: %v", err) + } } if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) @@ -2016,7 +2026,9 @@ func testIssue23496(t *testing.T, scheme string) { if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) { t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4)) } - if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { - t.Error("Failed to regenerate the snapshot of known state") + if scheme == rawdb.HashScheme { + if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { + t.Error("Failed to regenerate the snapshot of known state") + } } } diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index 424854b2bf..51e2a5275f 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -2023,7 +2023,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme } if tt.commitBlock > 0 { chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false) - if snapshots { + if snapshots && scheme == rawdb.HashScheme { if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { t.Fatalf("Failed to flatten snapshots: %v", err) } diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index 1a6fe38af6..23640fe843 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -105,7 +105,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo if basic.commitBlock > 0 && basic.commitBlock == point { chain.TrieDB().Commit(blocks[point-1].Root(), false) } - if basic.snapshotBlock > 0 && basic.snapshotBlock == point { + if basic.snapshotBlock > 0 && basic.snapshotBlock == point && basic.scheme == rawdb.HashScheme { // Flushing the entire snap tree into the disk, the // relevant (a) snapshot root and (b) snapshot generator // will be persisted atomically. @@ -149,13 +149,17 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [ block := chain.GetBlockByNumber(basic.expSnapshotBottom) if block == nil { t.Errorf("The corresponding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom) - } else if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) { - t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot()) + } else if basic.scheme == rawdb.HashScheme { + if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) { + t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot()) + } } // Check the snapshot, ensure it's integrated - if err := chain.snaps.Verify(block.Root()); err != nil { - t.Errorf("The disk layer is not integrated %v", err) + if basic.scheme == rawdb.HashScheme { + if err := chain.snaps.Verify(block.Root()); err != nil { + t.Errorf("The disk layer is not integrated %v", err) + } } } @@ -565,12 +569,14 @@ func TestHighCommitCrashWithNewSnapshot(t *testing.T) { // // Expected head header : C8 // Expected head fast block: C8 - // Expected head block : G - // Expected snapshot disk : C4 + // Expected head block : G (Hash mode), C6 (Hash mode) + // Expected snapshot disk : C4 (Hash mode) for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { expHead := uint64(0) if scheme == rawdb.PathScheme { - expHead = uint64(4) + // The pathdb database makes sure that snapshot and trie are consistent, + // so only the last two blocks are reverted in case of a crash. + expHead = uint64(6) } test := &crashSnapshotTest{ snapshotTestBasic{ diff --git a/core/state/database.go b/core/state/database.go index cef59cccfb..aec841f59b 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -175,26 +175,27 @@ func NewDatabaseForTesting() *CachingDB { func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) { var readers []StateReader - // Set up the state snapshot reader if available. This feature - // is optional and may be partially useful if it's not fully - // generated. - if db.snap != nil { - // If standalone state snapshot is available (hash scheme), - // then construct the legacy snap reader. + // Configure the state reader using the standalone snapshot in hash mode. + // This reader offers improved performance but is optional and only + // partially useful if the snapshot is not fully generated. + if db.TrieDB().Scheme() == rawdb.HashScheme && db.snap != nil { snap := db.snap.Snapshot(stateRoot) if snap != nil { readers = append(readers, newFlatReader(snap)) } - } else { - // If standalone state snapshot is not available, try to construct - // the state reader with database. + } + // Configure the state reader using the path database in path mode. + // This reader offers improved performance but is optional and only + // partially useful if the snapshot data in path database is not + // fully generated. + if db.TrieDB().Scheme() == rawdb.PathScheme { reader, err := db.triedb.StateReader(stateRoot) if err == nil { - readers = append(readers, newFlatReader(reader)) // state reader is optional + readers = append(readers, newFlatReader(reader)) } } - // Set up the trie reader, which is expected to always be available - // as the gatekeeper unless the state is corrupted. + // Configure the trie reader, which is expected to be available as the + // gatekeeper unless the state is corrupted. tr, err := newTrieReader(stateRoot, db.triedb, db.pointCache) if err != nil { return nil, err diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go index 3de7735ef8..3f83cb1a00 100644 --- a/core/state/snapshot/generate_test.go +++ b/core/state/snapshot/generate_test.go @@ -166,7 +166,9 @@ func newHelper(scheme string) *testHelper { diskdb := rawdb.NewMemoryDatabase() config := &triedb.Config{} if scheme == rawdb.PathScheme { - config.PathDB = &pathdb.Config{} // disable caching + config.PathDB = &pathdb.Config{ + SnapshotNoBuild: true, + } // disable caching } else { config.HashDB = &hashdb.Config{} // disable caching } diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index e740c64faa..709b5ed510 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -979,7 +979,8 @@ func testMissingTrieNodes(t *testing.T, scheme string) { ) if scheme == rawdb.PathScheme { tdb = triedb.NewDatabase(memDb, &triedb.Config{PathDB: &pathdb.Config{ - CleanCacheSize: 0, + TrieCleanSize: 0, + StateCleanSize: 0, WriteBufferSize: 0, }}) // disable caching } else { diff --git a/eth/handler.go b/eth/handler.go index 8283d7d02f..f563b47138 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/forkid" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -183,7 +184,7 @@ func newHandler(config *handlerConfig) (*handler, error) { } } // If snap sync is requested but snapshots are disabled, fail loudly - if h.snapSync.Load() && config.Chain.Snapshots() == nil { + if h.snapSync.Load() && (config.Chain.Snapshots() == nil && config.Chain.TrieDB().Scheme() == rawdb.HashScheme) { return nil, errors.New("snap sync not supported with snapshots disabled") } // Construct the downloader (long sync) diff --git a/eth/protocols/snap/handler.go b/eth/protocols/snap/handler.go index 924aff7ac9..3249720f90 100644 --- a/eth/protocols/snap/handler.go +++ b/eth/protocols/snap/handler.go @@ -23,6 +23,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -31,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/trienode" + "github.com/ethereum/go-ethereum/triedb/database" ) const ( @@ -279,7 +282,16 @@ func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePac if err != nil { return nil, nil } - it, err := chain.Snapshots().AccountIterator(req.Root, req.Origin) + // Temporary solution: using the snapshot interface for both cases. + // This can be removed once the hash scheme is deprecated. + var it snapshot.AccountIterator + if chain.TrieDB().Scheme() == rawdb.HashScheme { + // The snapshot is assumed to be available in hash mode if + // the SNAP protocol is enabled. + it, err = chain.Snapshots().AccountIterator(req.Root, req.Origin) + } else { + it, err = chain.TrieDB().AccountIterator(req.Root, req.Origin) + } if err != nil { return nil, nil } @@ -359,7 +371,19 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP limit, req.Limit = common.BytesToHash(req.Limit), nil } // Retrieve the requested state and bail out if non existent - it, err := chain.Snapshots().StorageIterator(req.Root, account, origin) + var ( + err error + it snapshot.StorageIterator + ) + // Temporary solution: using the snapshot interface for both cases. + // This can be removed once the hash scheme is deprecated. + if chain.TrieDB().Scheme() == rawdb.HashScheme { + // The snapshot is assumed to be available in hash mode if + // the SNAP protocol is enabled. + it, err = chain.Snapshots().StorageIterator(req.Root, account, origin) + } else { + it, err = chain.TrieDB().StorageIterator(req.Root, account, origin) + } if err != nil { return nil, nil } @@ -479,8 +503,15 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s // We don't have the requested state available, bail out return nil, nil } - // The 'snap' might be nil, in which case we cannot serve storage slots. - snap := chain.Snapshots().Snapshot(req.Root) + // The 'reader' might be nil, in which case we cannot serve storage slots + // via snapshot. + var reader database.StateReader + if chain.Snapshots() != nil { + reader = chain.Snapshots().Snapshot(req.Root) + } + if reader == nil { + reader, _ = triedb.StateReader(req.Root) + } // Retrieve trie nodes until the packet size limit is reached var ( nodes [][]byte @@ -505,8 +536,9 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s default: var stRoot common.Hash + // Storage slots requested, open the storage trie and retrieve from there - if snap == nil { + if reader == nil { // We don't have the requested state snapshotted yet (or it is stale), // but can look up the account via the trie instead. account, err := accTrie.GetAccountByHash(common.BytesToHash(pathset[0])) @@ -516,7 +548,7 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s } stRoot = account.Root } else { - account, err := snap.Account(common.BytesToHash(pathset[0])) + account, err := reader.Account(common.BytesToHash(pathset[0])) loads++ // always account database reads, even for failures if err != nil || account == nil { break diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go index d318077d99..d599e7ecc3 100644 --- a/eth/protocols/snap/sync_test.go +++ b/eth/protocols/snap/sync_test.go @@ -1962,5 +1962,5 @@ func newDbConfig(scheme string) *triedb.Config { if scheme == rawdb.HashScheme { return &triedb.Config{} } - return &triedb.Config{PathDB: pathdb.Defaults} + return &triedb.Config{PathDB: &pathdb.Config{SnapshotNoBuild: true}} } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 77bf945e40..f029fa7f41 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -187,8 +187,10 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t } // Cross-check the snapshot-to-hash against the trie hash if snapshotter { - if err := chain.Snapshots().Verify(chain.CurrentBlock().Root); err != nil { - return err + if chain.Snapshots() != nil { + if err := chain.Snapshots().Verify(chain.CurrentBlock().Root); err != nil { + return err + } } } return t.validateImportedHeaders(chain, validBlocks) diff --git a/trie/database_test.go b/trie/database_test.go index 729d9f699b..535f0d61b2 100644 --- a/trie/database_test.go +++ b/trie/database_test.go @@ -25,7 +25,7 @@ import ( "github.com/ethereum/go-ethereum/triedb/database" ) -// testReader implements database.Reader interface, providing function to +// testReader implements database.NodeReader interface, providing function to // access trie nodes. type testReader struct { db ethdb.Database @@ -33,7 +33,7 @@ type testReader struct { nodes []*trienode.MergedNodeSet // sorted from new to old } -// Node implements database.Reader interface, retrieving trie node with +// Node implements database.NodeReader interface, retrieving trie node with // all available cached layers. func (r *testReader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) { // Check the node presence with the cached layer, from latest to oldest. @@ -54,7 +54,7 @@ func (r *testReader) Node(owner common.Hash, path []byte, hash common.Hash) ([]b return rawdb.ReadTrieNode(r.db, owner, path, hash, r.scheme), nil } -// testDb implements database.Database interface, using for testing purpose. +// testDb implements database.NodeDatabase interface, using for testing purpose. type testDb struct { disk ethdb.Database root common.Hash diff --git a/triedb/database.go b/triedb/database.go index f8ccc5ad33..18e24cd176 100644 --- a/triedb/database.go +++ b/triedb/database.go @@ -312,6 +312,26 @@ func (db *Database) Journal(root common.Hash) error { return pdb.Journal(root) } +// AccountIterator creates a new account iterator for the specified root hash and +// seeks to a starting account hash. +func (db *Database) AccountIterator(root common.Hash, seek common.Hash) (pathdb.AccountIterator, error) { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return nil, errors.New("not supported") + } + return pdb.AccountIterator(root, seek) +} + +// StorageIterator creates a new storage iterator for the specified root hash and +// account. The iterator will be move to the specific start position. +func (db *Database) StorageIterator(root common.Hash, account common.Hash, seek common.Hash) (pathdb.StorageIterator, error) { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return nil, errors.New("not supported") + } + return pdb.StorageIterator(root, account, seek) +} + // IsVerkle returns the indicator if the database is holding a verkle tree. func (db *Database) IsVerkle() bool { return db.config.IsVerkle diff --git a/triedb/pathdb/buffer.go b/triedb/pathdb/buffer.go index c4e081b973..e639a43835 100644 --- a/triedb/pathdb/buffer.go +++ b/triedb/pathdb/buffer.go @@ -124,7 +124,7 @@ func (b *buffer) size() uint64 { // flush persists the in-memory dirty trie node into the disk if the configured // memory threshold is reached. Note, all data must be written atomically. -func (b *buffer) flush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, nodesCache *fastcache.Cache, id uint64) error { +func (b *buffer) flush(root common.Hash, db ethdb.KeyValueStore, freezer ethdb.AncientWriter, progress []byte, nodesCache, statesCache *fastcache.Cache, id uint64) error { // Ensure the target state id is aligned with the internal counter. head := rawdb.ReadPersistentStateID(db) if head+b.layers != id { @@ -133,7 +133,7 @@ func (b *buffer) flush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, node // Terminate the state snapshot generation if it's active var ( start = time.Now() - batch = db.NewBatchWithSize(b.nodes.dbsize() * 11 / 10) // extra 10% for potential pebble internal stuff + batch = db.NewBatchWithSize((b.nodes.dbsize() + b.states.dbsize()) * 11 / 10) // extra 10% for potential pebble internal stuff ) // Explicitly sync the state freezer to ensure all written data is persisted to disk // before updating the key-value store. @@ -146,7 +146,9 @@ func (b *buffer) flush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, node } } nodes := b.nodes.write(batch, nodesCache) + accounts, slots := b.states.write(batch, progress, statesCache) rawdb.WritePersistentStateID(batch, id) + rawdb.WriteSnapshotRoot(batch, root) // Flush all mutations in a single batch size := batch.ValueSize() @@ -155,8 +157,10 @@ func (b *buffer) flush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, node } commitBytesMeter.Mark(int64(size)) commitNodesMeter.Mark(int64(nodes)) + commitAccountsMeter.Mark(int64(accounts)) + commitStoragesMeter.Mark(int64(slots)) commitTimeTimer.UpdateSince(start) b.reset() - log.Debug("Persisted buffer content", "nodes", nodes, "bytes", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start))) + log.Debug("Persisted buffer content", "nodes", nodes, "accounts", accounts, "slots", slots, "bytes", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start))) return nil } diff --git a/triedb/pathdb/context.go b/triedb/pathdb/context.go new file mode 100644 index 0000000000..a5704de81a --- /dev/null +++ b/triedb/pathdb/context.go @@ -0,0 +1,246 @@ +// Copyright 2024 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 . + +package pathdb + +import ( + "bytes" + "encoding/binary" + "errors" + "math" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/log" +) + +const ( + snapAccount = "account" // Identifier of account snapshot generation + snapStorage = "storage" // Identifier of storage snapshot generation +) + +// generatorStats is a collection of statistics gathered by the snapshot generator +// for logging purposes. This data structure is used throughout the entire +// lifecycle of the snapshot generation process and is shared across multiple +// generation cycles. +type generatorStats struct { + origin uint64 // Origin prefix where generation started + start time.Time // Timestamp when generation started + accounts uint64 // Number of accounts indexed(generated or recovered) + slots uint64 // Number of storage slots indexed(generated or recovered) + dangling uint64 // Number of dangling storage slots + storage common.StorageSize // Total account and storage slot size(generation or recovery) +} + +// log creates a contextual log with the given message and the context pulled +// from the internally maintained statistics. +func (gs *generatorStats) log(msg string, root common.Hash, marker []byte) { + var ctx []interface{} + if root != (common.Hash{}) { + ctx = append(ctx, []interface{}{"root", root}...) + } + // Figure out whether we're after or within an account + switch len(marker) { + case common.HashLength: + ctx = append(ctx, []interface{}{"at", common.BytesToHash(marker)}...) + case 2 * common.HashLength: + ctx = append(ctx, []interface{}{ + "in", common.BytesToHash(marker[:common.HashLength]), + "at", common.BytesToHash(marker[common.HashLength:]), + }...) + } + // Add the usual measurements + ctx = append(ctx, []interface{}{ + "accounts", gs.accounts, + "slots", gs.slots, + "storage", gs.storage, + "dangling", gs.dangling, + "elapsed", common.PrettyDuration(time.Since(gs.start)), + }...) + // Calculate the estimated indexing time based on current stats + if len(marker) > 0 { + if done := binary.BigEndian.Uint64(marker[:8]) - gs.origin; done > 0 { + left := math.MaxUint64 - binary.BigEndian.Uint64(marker[:8]) + + speed := done/uint64(time.Since(gs.start)/time.Millisecond+1) + 1 // +1s to avoid division by zero + ctx = append(ctx, []interface{}{ + "eta", common.PrettyDuration(time.Duration(left/speed) * time.Millisecond), + }...) + } + } + log.Info(msg, ctx...) +} + +// generatorContext holds several global fields that are used throughout the +// current generation cycle. It must be recreated if the generation cycle is +// restarted. +type generatorContext struct { + root common.Hash // State root of the generation target + account *holdableIterator // Iterator of account snapshot data + storage *holdableIterator // Iterator of storage snapshot data + db ethdb.KeyValueStore // Key-value store containing the snapshot data + batch ethdb.Batch // Database batch for writing data atomically + logged time.Time // The timestamp when last generation progress was displayed +} + +// newGeneratorContext initializes the context for generation. +func newGeneratorContext(root common.Hash, marker []byte, db ethdb.KeyValueStore) *generatorContext { + ctx := &generatorContext{ + root: root, + db: db, + batch: db.NewBatch(), + logged: time.Now(), + } + accMarker, storageMarker := splitMarker(marker) + ctx.openIterator(snapAccount, accMarker) + ctx.openIterator(snapStorage, storageMarker) + return ctx +} + +// openIterator constructs global account and storage snapshot iterators +// at the interrupted position. These iterators should be reopened from time +// to time to avoid blocking leveldb compaction for a long time. +func (ctx *generatorContext) openIterator(kind string, start []byte) { + if kind == snapAccount { + iter := ctx.db.NewIterator(rawdb.SnapshotAccountPrefix, start) + ctx.account = newHoldableIterator(rawdb.NewKeyLengthIterator(iter, 1+common.HashLength)) + return + } + iter := ctx.db.NewIterator(rawdb.SnapshotStoragePrefix, start) + ctx.storage = newHoldableIterator(rawdb.NewKeyLengthIterator(iter, 1+2*common.HashLength)) +} + +// reopenIterator releases the specified snapshot iterator and re-open it +// in the next position. It's aimed for not blocking leveldb compaction. +func (ctx *generatorContext) reopenIterator(kind string) { + // Shift iterator one more step, so that we can reopen + // the iterator at the right position. + var iter = ctx.account + if kind == snapStorage { + iter = ctx.storage + } + hasNext := iter.Next() + if !hasNext { + // Iterator exhausted, release forever and create an already exhausted virtual iterator + iter.Release() + if kind == snapAccount { + ctx.account = newHoldableIterator(memorydb.New().NewIterator(nil, nil)) + return + } + ctx.storage = newHoldableIterator(memorydb.New().NewIterator(nil, nil)) + return + } + next := iter.Key() + iter.Release() + ctx.openIterator(kind, next[1:]) +} + +// close releases all the held resources. +func (ctx *generatorContext) close() { + ctx.account.Release() + ctx.storage.Release() +} + +// iterator returns the corresponding iterator specified by the kind. +func (ctx *generatorContext) iterator(kind string) *holdableIterator { + if kind == snapAccount { + return ctx.account + } + return ctx.storage +} + +// removeStorageBefore deletes all storage entries which are located before +// the specified account. When the iterator touches the storage entry which +// is located in or outside the given account, it stops and holds the current +// iterated element locally. +func (ctx *generatorContext) removeStorageBefore(account common.Hash) uint64 { + var ( + count uint64 + start = time.Now() + iter = ctx.storage + ) + for iter.Next() { + key := iter.Key() + if bytes.Compare(key[1:1+common.HashLength], account.Bytes()) >= 0 { + iter.Hold() + break + } + count++ + ctx.batch.Delete(key) + if ctx.batch.ValueSize() > ethdb.IdealBatchSize { + ctx.batch.Write() + ctx.batch.Reset() + } + } + storageCleanCounter.Inc(time.Since(start).Nanoseconds()) + return count +} + +// removeStorageAt deletes all storage entries which are located in the specified +// account. When the iterator touches the storage entry which is outside the given +// account, it stops and holds the current iterated element locally. An error will +// be returned if the initial position of iterator is not in the given account. +func (ctx *generatorContext) removeStorageAt(account common.Hash) error { + var ( + count int64 + start = time.Now() + iter = ctx.storage + ) + for iter.Next() { + key := iter.Key() + cmp := bytes.Compare(key[1:1+common.HashLength], account.Bytes()) + if cmp < 0 { + return errors.New("invalid iterator position") + } + if cmp > 0 { + iter.Hold() + break + } + count++ + ctx.batch.Delete(key) + if ctx.batch.ValueSize() > ethdb.IdealBatchSize { + ctx.batch.Write() + ctx.batch.Reset() + } + } + wipedStorageMeter.Mark(count) + storageCleanCounter.Inc(time.Since(start).Nanoseconds()) + return nil +} + +// removeRemainingStorage deletes all storage entries which are located after +// the current iterator position. +func (ctx *generatorContext) removeRemainingStorage() uint64 { + var ( + count uint64 + start = time.Now() + iter = ctx.storage + ) + for iter.Next() { + count++ + ctx.batch.Delete(iter.Key()) + if ctx.batch.ValueSize() > ethdb.IdealBatchSize { + ctx.batch.Write() + ctx.batch.Reset() + } + } + danglingStorageMeter.Mark(int64(count)) + storageCleanCounter.Inc(time.Since(start).Nanoseconds()) + return count +} diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index 155e28543d..c206460315 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -17,6 +17,7 @@ package pathdb import ( + "encoding/binary" "errors" "fmt" "io" @@ -35,8 +36,11 @@ import ( ) const ( - // defaultCleanSize is the default memory allowance of clean cache. - defaultCleanSize = 16 * 1024 * 1024 + // defaultTrieCleanSize is the default memory allowance of clean trie cache. + defaultTrieCleanSize = 16 * 1024 * 1024 + + // defaultStateCleanSize is the default memory allowance of clean state cache. + defaultStateCleanSize = 16 * 1024 * 1024 // maxBufferSize is the maximum memory allowance of node buffer. // Too large buffer will cause the system to pause for a long @@ -111,9 +115,11 @@ type layer interface { // Config contains the settings for database. type Config struct { StateHistory uint64 // Number of recent blocks to maintain state history for - CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes + TrieCleanSize int // Maximum memory allowance (in bytes) for caching clean trie nodes + StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer - ReadOnly bool // Flag whether the database is opened in read only mode. + ReadOnly bool // Flag whether the database is opened in read only mode + SnapshotNoBuild bool // Flag Whether the background generation is allowed } // sanitize checks the provided user configurations and changes anything that's @@ -133,7 +139,11 @@ func (c *Config) fields() []interface{} { if c.ReadOnly { list = append(list, "readonly", true) } - list = append(list, "cache", common.StorageSize(c.CleanCacheSize)) + if c.SnapshotNoBuild { + list = append(list, "snapshot", false) + } + list = append(list, "triecache", common.StorageSize(c.TrieCleanSize)) + list = append(list, "statecache", common.StorageSize(c.StateCleanSize)) list = append(list, "buffer", common.StorageSize(c.WriteBufferSize)) list = append(list, "history", c.StateHistory) return list @@ -142,7 +152,8 @@ func (c *Config) fields() []interface{} { // Defaults contains default settings for Ethereum mainnet. var Defaults = &Config{ StateHistory: params.FullImmutabilityThreshold, - CleanCacheSize: defaultCleanSize, + TrieCleanSize: defaultTrieCleanSize, + StateCleanSize: defaultStateCleanSize, WriteBufferSize: defaultBufferSize, } @@ -240,6 +251,13 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database { log.Crit("Failed to disable database", "err", err) // impossible to happen } } + // Resolving the state snapshot generation progress from the database is + // mandatory. This ensures that uncovered flat states are not accessed, + // even if background generation is not allowed. If permitted, the generation + // might be scheduled. + if err := db.setStateGenerator(); err != nil { + log.Crit("Failed to setup the generator", "err", err) + } fields := config.fields() if db.isVerkle { fields = append(fields, "verkle", true) @@ -297,6 +315,60 @@ func (db *Database) repairHistory() error { return nil } +// setStateGenerator loads the state generation progress marker and potentially +// resume the state generation if it's permitted. +func (db *Database) setStateGenerator() error { + // Load the state snapshot generation progress marker to prevent access + // to uncovered states. + generator, root, err := loadGenerator(db.diskdb, db.hasher) + if err != nil { + return err + } + if generator == nil { + // Initialize an empty generator to rebuild the state snapshot from scratch + generator = &journalGenerator{ + Marker: []byte{}, + } + } + // Short circuit if the whole state snapshot has already been fully generated. + // The generator will be left as nil in disk layer for representing the whole + // state snapshot is available for accessing. + if generator.Done { + return nil + } + var origin uint64 + if len(generator.Marker) >= 8 { + origin = binary.BigEndian.Uint64(generator.Marker) + } + stats := &generatorStats{ + origin: origin, + start: time.Now(), + accounts: generator.Accounts, + slots: generator.Slots, + storage: common.StorageSize(generator.Storage), + } + dl := db.tree.bottom() + + // Disable the background snapshot building in these circumstances: + // - the database is opened in read only mode + // - the snapshot build is explicitly disabled + // - the database is opened in verkle tree mode + noBuild := db.readOnly || db.config.SnapshotNoBuild || db.isVerkle + + // Construct the generator and link it to the disk layer, ensuring that the + // generation progress is resolved to prevent accessing uncovered states + // regardless of whether background state snapshot generation is allowed. + dl.setGenerator(newGenerator(db.diskdb, noBuild, generator.Marker, stats)) + + // Short circuit if the background generation is not permitted + if noBuild || db.waitSync { + return nil + } + stats.log("Starting snapshot generation", root, generator.Marker) + dl.generator.run(root) + return nil +} + // Update adds a new layer into the tree, if that can be linked to an existing // old parent. It is disallowed to insert a disk layer (the origin of all). Apart // from that this function will flatten the extra diff layers at bottom into disk @@ -359,8 +431,13 @@ func (db *Database) Disable() error { } db.waitSync = true - // Mark the disk layer as stale to prevent access to persistent state. - db.tree.bottom().markStale() + // Terminate the state generator if it's active and mark the disk layer + // as stale to prevent access to persistent state. + disk := db.tree.bottom() + if disk.generator != nil { + disk.generator.stop() + } + disk.markStale() // Write the initial sync flag to persist it across restarts. rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncRunning) @@ -390,6 +467,7 @@ func (db *Database) Enable(root common.Hash) error { // reset the persistent state id back to zero. batch := db.diskdb.NewBatch() rawdb.DeleteTrieJournal(batch) + rawdb.DeleteSnapshotRoot(batch) rawdb.WritePersistentStateID(batch, 0) if err := batch.Write(); err != nil { return err @@ -403,13 +481,13 @@ func (db *Database) Enable(root common.Hash) error { return err } } - // Re-construct a new disk layer backed by persistent state - // with **empty clean cache and node buffer**. - db.tree.reset(newDiskLayer(root, 0, db, nil, newBuffer(db.config.WriteBufferSize, nil, nil, 0))) - // Re-enable the database as the final step. db.waitSync = false rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncFinished) + + // Re-construct a new disk layer backed by persistent state + // and schedule the state snapshot generation if it's permitted. + db.tree.reset(generateSnapshot(db, root, db.isVerkle || db.config.SnapshotNoBuild)) log.Info("Rebuilt trie database", "root", root) return nil } @@ -514,8 +592,12 @@ func (db *Database) Close() error { // following mutations. db.readOnly = true - // Release the memory held by clean cache. - db.tree.bottom().resetCache() + // Terminate the background generation if it's active + disk := db.tree.bottom() + if disk.generator != nil { + disk.generator.stop() + } + disk.resetCache() // release the memory held by clean cache // Close the attached state history freezer. if db.freezer == nil { @@ -580,14 +662,42 @@ func (db *Database) HistoryRange() (uint64, uint64, error) { return historyRange(db.freezer) } +// waitGeneration waits until the background generation is finished. It assumes +// that the generation is permitted; otherwise, it will block indefinitely. +func (db *Database) waitGeneration() { + gen := db.tree.bottom().generator + if gen == nil || gen.completed() { + return + } + <-gen.done +} + // AccountIterator creates a new account iterator for the specified root hash and // seeks to a starting account hash. func (db *Database) AccountIterator(root common.Hash, seek common.Hash) (AccountIterator, error) { + db.lock.RLock() + wait := db.waitSync + db.lock.RUnlock() + if wait { + return nil, errDatabaseWaitSync + } + if gen := db.tree.bottom().generator; gen != nil && !gen.completed() { + return nil, errNotConstructed + } return newFastAccountIterator(db, root, seek) } // StorageIterator creates a new storage iterator for the specified root hash and // account. The iterator will be moved to the specific start position. func (db *Database) StorageIterator(root common.Hash, account common.Hash, seek common.Hash) (StorageIterator, error) { + db.lock.RLock() + wait := db.waitSync + db.lock.RUnlock() + if wait { + return nil, errDatabaseWaitSync + } + if gen := db.tree.bottom().generator; gen != nil && !gen.completed() { + return nil, errNotConstructed + } return newFastStorageIterator(db, root, account, seek) } diff --git a/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go index c85d7832ee..3b780c975d 100644 --- a/triedb/pathdb/database_test.go +++ b/triedb/pathdb/database_test.go @@ -126,7 +126,8 @@ func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int) *te disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) db = New(disk, &Config{ StateHistory: historyLimit, - CleanCacheSize: 256 * 1024, + TrieCleanSize: 256 * 1024, + StateCleanSize: 256 * 1024, WriteBufferSize: 256 * 1024, }, isVerkle) diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index b8869888d9..bee4cd1e8a 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -17,9 +17,10 @@ package pathdb import ( - "errors" + "bytes" "fmt" "sync" + "time" "github.com/VictoriaMetrics/fastcache" "github.com/ethereum/go-ethereum/common" @@ -30,28 +31,42 @@ import ( // diskLayer is a low level persistent layer built on top of a key-value store. type diskLayer struct { - root common.Hash // Immutable, root hash to which this layer was made for - id uint64 // Immutable, corresponding state id - db *Database // Path-based trie database + root common.Hash // Immutable, root hash to which this layer was made for + id uint64 // Immutable, corresponding state id + db *Database // Path-based trie database + + // These two caches must be maintained separately, because the key + // for the root node of the storage trie (accountHash) is identical + // to the key for the account data. nodes *fastcache.Cache // GC friendly memory cache of clean nodes - buffer *buffer // Dirty buffer to aggregate writes of nodes and states - stale bool // Signals that the layer became stale (state progressed) - lock sync.RWMutex // Lock used to protect stale flag + states *fastcache.Cache // GC friendly memory cache of clean states + + buffer *buffer // Dirty buffer to aggregate writes of nodes and states + stale bool // Signals that the layer became stale (state progressed) + lock sync.RWMutex // Lock used to protect stale flag and genMarker + + // The generator is set if the state snapshot was not fully completed, + // regardless of whether the background generation is running or not. + generator *generator } // newDiskLayer creates a new disk layer based on the passing arguments. -func newDiskLayer(root common.Hash, id uint64, db *Database, nodes *fastcache.Cache, buffer *buffer) *diskLayer { - // Initialize a clean cache if the memory allowance is not zero - // or reuse the provided cache if it is not nil (inherited from +func newDiskLayer(root common.Hash, id uint64, db *Database, nodes *fastcache.Cache, states *fastcache.Cache, buffer *buffer) *diskLayer { + // Initialize the clean caches if the memory allowance is not zero + // or reuse the provided caches if they are not nil (inherited from // the original disk layer). - if nodes == nil && db.config.CleanCacheSize != 0 { - nodes = fastcache.New(db.config.CleanCacheSize) + if nodes == nil && db.config.TrieCleanSize != 0 { + nodes = fastcache.New(db.config.TrieCleanSize) + } + if states == nil && db.config.StateCleanSize != 0 { + states = fastcache.New(db.config.StateCleanSize) } return &diskLayer{ root: root, id: id, db: db, nodes: nodes, + states: states, buffer: buffer, } } @@ -72,6 +87,13 @@ func (dl *diskLayer) parentLayer() layer { return nil } +// setGenerator links the given generator to disk layer, representing the +// associated state snapshot is not fully completed yet and the generation +// is potentially running in the background. +func (dl *diskLayer) setGenerator(generator *generator) { + dl.generator = generator +} + // isStale return whether this layer has become stale (was flattened across) or if // it's still live. func (dl *diskLayer) isStale() bool { @@ -168,8 +190,41 @@ func (dl *diskLayer) account(hash common.Hash, depth int) ([]byte, error) { } dirtyStateMissMeter.Mark(1) - // TODO(rjl493456442) support persistent state retrieval - return nil, errors.New("not supported") + // If the layer is being generated, ensure the requested account has + // already been covered by the generator. + marker := dl.genMarker() + if marker != nil && bytes.Compare(hash.Bytes(), marker) > 0 { + return nil, errNotCoveredYet + } + // Try to retrieve the account from the memory cache + if dl.states != nil { + if blob, found := dl.states.HasGet(nil, hash[:]); found { + cleanStateHitMeter.Mark(1) + cleanStateReadMeter.Mark(int64(len(blob))) + + if len(blob) == 0 { + stateAccountInexMeter.Mark(1) + } else { + stateAccountExistMeter.Mark(1) + } + return blob, nil + } + cleanStateMissMeter.Mark(1) + } + // Try to retrieve the account from the disk. + blob = rawdb.ReadAccountSnapshot(dl.db.diskdb, hash) + if dl.states != nil { + dl.states.Set(hash[:], blob) + cleanStateWriteMeter.Mark(int64(len(blob))) + } + if len(blob) == 0 { + stateAccountInexMeter.Mark(1) + stateAccountInexDiskMeter.Mark(1) + } else { + stateAccountExistMeter.Mark(1) + stateAccountExistDiskMeter.Mark(1) + } + return blob, nil } // storage directly retrieves the storage data associated with a particular hash, @@ -203,8 +258,42 @@ func (dl *diskLayer) storage(accountHash, storageHash common.Hash, depth int) ([ } dirtyStateMissMeter.Mark(1) - // TODO(rjl493456442) support persistent state retrieval - return nil, errors.New("not supported") + // If the layer is being generated, ensure the requested storage slot + // has already been covered by the generator. + key := append(accountHash[:], storageHash[:]...) + marker := dl.genMarker() + if marker != nil && bytes.Compare(key, marker) > 0 { + return nil, errNotCoveredYet + } + // Try to retrieve the storage slot from the memory cache + if dl.states != nil { + if blob, found := dl.states.HasGet(nil, key); found { + cleanStateHitMeter.Mark(1) + cleanStateReadMeter.Mark(int64(len(blob))) + + if len(blob) == 0 { + stateStorageInexMeter.Mark(1) + } else { + stateStorageExistMeter.Mark(1) + } + return blob, nil + } + cleanStateMissMeter.Mark(1) + } + // Try to retrieve the account from the disk + blob := rawdb.ReadStorageSnapshot(dl.db.diskdb, accountHash, storageHash) + if dl.states != nil { + dl.states.Set(key, blob) + cleanStateWriteMeter.Mark(int64(len(blob))) + } + if len(blob) == 0 { + stateStorageInexMeter.Mark(1) + stateStorageInexDiskMeter.Mark(1) + } else { + stateStorageExistMeter.Mark(1) + stateStorageExistDiskMeter.Mark(1) + } + return blob, nil } // update implements the layer interface, returning a new diff layer on top @@ -267,13 +356,39 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { // Merge the trie nodes and flat states of the bottom-most diff layer into the // buffer as the combined layer. combined := dl.buffer.commit(bottom.nodes, bottom.states.stateSet) + + // Terminate the background state snapshot generation before mutating the + // persistent state. if combined.full() || force { - if err := combined.flush(dl.db.diskdb, dl.db.freezer, dl.nodes, bottom.stateID()); err != nil { + // Terminate the background state snapshot generator before flushing + // to prevent data race. + var progress []byte + if dl.generator != nil { + dl.generator.stop() + progress = dl.generator.progressMarker() + + // If the snapshot has been fully generated, unset the generator + if progress == nil { + dl.setGenerator(nil) + } else { + log.Info("Paused snapshot generation") + } + } + // Flush the content in combined buffer. Any state data after the progress + // marker will be ignored, as the generator will pick it up later. + if err := combined.flush(bottom.root, dl.db.diskdb, dl.db.freezer, progress, dl.nodes, dl.states, bottom.stateID()); err != nil { return nil, err } + // Resume the background generation if it's not completed yet + if progress != nil { + dl.generator.run(bottom.root) + } + } + // Link the generator if snapshot is not yet completed + ndl := newDiskLayer(bottom.root, bottom.stateID(), dl.db, dl.nodes, dl.states, combined) + if dl.generator != nil { + ndl.setGenerator(dl.generator) } - ndl := newDiskLayer(bottom.root, bottom.stateID(), dl.db, dl.nodes, combined) - // To remove outdated history objects from the end, we set the 'tail' parameter // to 'oldest-1' due to the offset between the freezer index and the history ID. if overflow { @@ -288,6 +403,7 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { // revert applies the given state history and return a reverted disk layer. func (dl *diskLayer) revert(h *history) (*diskLayer, error) { + start := time.Now() if h.meta.root != dl.rootHash() { return nil, errUnexpectedHistory } @@ -321,15 +437,40 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) { if err != nil { return nil, err } - } else { - batch := dl.db.diskdb.NewBatch() - writeNodes(batch, nodes, dl.nodes) - rawdb.WritePersistentStateID(batch, dl.id-1) - if err := batch.Write(); err != nil { - log.Crit("Failed to write states", "err", err) + ndl := newDiskLayer(h.meta.parent, dl.id-1, dl.db, dl.nodes, dl.states, dl.buffer) + + // Link the generator if it exists + if dl.generator != nil { + ndl.setGenerator(dl.generator) } + log.Debug("Reverted data in write buffer", "oldroot", h.meta.root, "newroot", h.meta.parent, "elapsed", common.PrettyDuration(time.Since(start))) + return ndl, nil } - return newDiskLayer(h.meta.parent, dl.id-1, dl.db, dl.nodes, dl.buffer), nil + // Terminate the generation before writing any data into database + var progress []byte + if dl.generator != nil { + dl.generator.stop() + progress = dl.generator.progressMarker() + } + batch := dl.db.diskdb.NewBatch() + writeNodes(batch, nodes, dl.nodes) + + // Provide the original values of modified accounts and storages for revert + writeStates(batch, progress, accounts, storages, dl.states) + rawdb.WritePersistentStateID(batch, dl.id-1) + rawdb.WriteSnapshotRoot(batch, h.meta.parent) + if err := batch.Write(); err != nil { + log.Crit("Failed to write states", "err", err) + } + // Link the generator and resume generation if the snapshot is not yet + // fully completed. + ndl := newDiskLayer(h.meta.parent, dl.id-1, dl.db, dl.nodes, dl.states, dl.buffer) + if dl.generator != nil && !dl.generator.completed() { + ndl.generator = dl.generator + ndl.generator.run(h.meta.parent) + } + log.Debug("Reverted data in persistent state", "oldroot", h.meta.root, "newroot", h.meta.parent, "elapsed", common.PrettyDuration(time.Since(start))) + return ndl, nil } // size returns the approximate size of cached nodes in the disk layer. @@ -355,4 +496,16 @@ func (dl *diskLayer) resetCache() { if dl.nodes != nil { dl.nodes.Reset() } + if dl.states != nil { + dl.states.Reset() + } +} + +// genMarker returns the current state snapshot generation progress marker. If +// the state snapshot has already been fully generated, nil is returned. +func (dl *diskLayer) genMarker() []byte { + if dl.generator == nil { + return nil + } + return dl.generator.progressMarker() } diff --git a/triedb/pathdb/errors.go b/triedb/pathdb/errors.go index 49e9c3ca64..5d953b2183 100644 --- a/triedb/pathdb/errors.go +++ b/triedb/pathdb/errors.go @@ -39,4 +39,13 @@ var ( // errStateUnrecoverable is returned if state is required to be reverted to // a destination without associated state history available. errStateUnrecoverable = errors.New("state is unrecoverable") + + // errNotCoveredYet is returned from data accessors if the underlying snapshot + // is being generated currently and the requested data item is not yet in the + // range of accounts covered. + errNotCoveredYet = errors.New("not covered yet") + + // errNotConstructed is returned if the callers want to iterate the snapshot + // while the generation is not finished yet. + errNotConstructed = errors.New("snapshot is not constructed") ) diff --git a/triedb/pathdb/flush.go b/triedb/pathdb/flush.go index baa0bfb292..6563dbccff 100644 --- a/triedb/pathdb/flush.go +++ b/triedb/pathdb/flush.go @@ -17,6 +17,8 @@ package pathdb import ( + "bytes" + "github.com/VictoriaMetrics/fastcache" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -63,3 +65,69 @@ func writeNodes(batch ethdb.Batch, nodes map[common.Hash]map[string]*trienode.No } return total } + +// writeStates flushes state mutations into the provided database batch as a whole. +// +// This function assumes the background generator is already terminated and states +// before the supplied marker has been correctly generated. +// +// TODO(rjl493456442) do we really need this generation marker? The state updates +// after the marker can also be written and will be fixed by generator later if +// it's outdated. +func writeStates(batch ethdb.Batch, genMarker []byte, accountData map[common.Hash][]byte, storageData map[common.Hash]map[common.Hash][]byte, clean *fastcache.Cache) (int, int) { + var ( + accounts int + slots int + ) + for addrHash, blob := range accountData { + // Skip any account not yet covered by the snapshot. The account + // at the generation marker position (addrHash == genMarker[:common.HashLength]) + // should still be updated, as it would be skipped in the next + // generation cycle. + if genMarker != nil && bytes.Compare(addrHash[:], genMarker) > 0 { + continue + } + accounts += 1 + if len(blob) == 0 { + rawdb.DeleteAccountSnapshot(batch, addrHash) + if clean != nil { + clean.Set(addrHash[:], nil) + } + } else { + rawdb.WriteAccountSnapshot(batch, addrHash, blob) + if clean != nil { + clean.Set(addrHash[:], blob) + } + } + } + for addrHash, storages := range storageData { + // Skip any account not covered yet by the snapshot + if genMarker != nil && bytes.Compare(addrHash[:], genMarker) > 0 { + continue + } + midAccount := genMarker != nil && bytes.Equal(addrHash[:], genMarker[:common.HashLength]) + + for storageHash, blob := range storages { + // Skip any storage slot not yet covered by the snapshot. The storage slot + // at the generation marker position (addrHash == genMarker[:common.HashLength] + // and storageHash == genMarker[common.HashLength:]) should still be updated, + // as it would be skipped in the next generation cycle. + if midAccount && bytes.Compare(storageHash[:], genMarker[common.HashLength:]) > 0 { + continue + } + slots += 1 + if len(blob) == 0 { + rawdb.DeleteStorageSnapshot(batch, addrHash, storageHash) + if clean != nil { + clean.Set(append(addrHash[:], storageHash[:]...), nil) + } + } else { + rawdb.WriteStorageSnapshot(batch, addrHash, storageHash, blob) + if clean != nil { + clean.Set(append(addrHash[:], storageHash[:]...), blob) + } + } + } + } + return accounts, slots +} diff --git a/triedb/pathdb/generate.go b/triedb/pathdb/generate.go new file mode 100644 index 0000000000..f4f98c9d19 --- /dev/null +++ b/triedb/pathdb/generate.go @@ -0,0 +1,856 @@ +// Copyright 2019 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 . + +package pathdb + +import ( + "bytes" + "errors" + "fmt" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/triedb/database" +) + +var ( + // accountCheckRange is the upper limit of the number of accounts involved in + // each range check. This is a value estimated based on experience. If this + // range is too large, the failure rate of range proof will increase. Otherwise, + // if the range is too small, the efficiency of the state recovery will decrease. + accountCheckRange = 128 + + // storageCheckRange is the upper limit of the number of storage slots involved + // in each range check. This is a value estimated based on experience. If this + // range is too large, the failure rate of range proof will increase. Otherwise, + // if the range is too small, the efficiency of the state recovery will decrease. + storageCheckRange = 1024 + + // errMissingTrie is returned if the target trie is missing while the generation + // is running. In this case the generation is aborted and wait the new signal. + errMissingTrie = errors.New("missing trie") +) + +// diskReader is a wrapper of key-value store and implements database.NodeReader, +// providing a function for accessing persistent trie nodes in the disk +type diskReader struct{ db ethdb.KeyValueStore } + +// Node retrieves the trie node blob with the provided trie identifier, +// node path and the corresponding node hash. No error will be returned +// if the node is not found. +func (r *diskReader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) { + if owner == (common.Hash{}) { + return rawdb.ReadAccountTrieNode(r.db, path), nil + } + return rawdb.ReadStorageTrieNode(r.db, owner, path), nil +} + +// diskStore is a wrapper of key-value store and implements database.NodeDatabase. +// It's meant to be used for generating state snapshot from the trie data. +type diskStore struct { + db ethdb.KeyValueStore +} + +// NodeReader returns a node reader associated with the specific state. +// An error will be returned if the specified state is not available. +func (s *diskStore) NodeReader(stateRoot common.Hash) (database.NodeReader, error) { + root := types.EmptyRootHash + if blob := rawdb.ReadAccountTrieNode(s.db, nil); len(blob) > 0 { + root = crypto.Keccak256Hash(blob) + } + if root != stateRoot { + return nil, fmt.Errorf("state %x is not available", stateRoot) + } + return &diskReader{s.db}, nil +} + +// Generator is the struct for initial state snapshot generation. It is not thread-safe; +// the caller must manage concurrency issues themselves. +type generator struct { + noBuild bool // Flag indicating whether snapshot generation is permitted + running bool // Flag indicating whether the background generation is running + + db ethdb.KeyValueStore // Key-value store containing the snapshot data + stats *generatorStats // Generation statistics used throughout the entire life cycle + abort chan chan struct{} // Notification channel to abort generating the snapshot in this layer + done chan struct{} // Notification channel when generation is done + + progress []byte // Progress marker of the state generation, nil means it's completed + lock sync.RWMutex // Lock which protects the progress, only generator can mutate the progress +} + +// newGenerator constructs the state snapshot generator. +// +// noBuild will be true if the background snapshot generation is not allowed, +// usually used in read-only mode. +// +// progress indicates the starting position for resuming snapshot generation. +// It must be provided even if generation is not allowed; otherwise, uncovered +// states may be exposed for serving. +func newGenerator(db ethdb.KeyValueStore, noBuild bool, progress []byte, stats *generatorStats) *generator { + if stats == nil { + stats = &generatorStats{start: time.Now()} + } + return &generator{ + noBuild: noBuild, + progress: progress, + db: db, + stats: stats, + abort: make(chan chan struct{}), + done: make(chan struct{}), + } +} + +// run starts the state snapshot generation in the background. +func (g *generator) run(root common.Hash) { + if g.noBuild { + log.Warn("Snapshot generation is not permitted") + return + } + if g.running { + g.stop() + log.Warn("Paused the leftover generation cycle") + } + g.running = true + go g.generate(newGeneratorContext(root, g.progress, g.db)) +} + +// stop terminates the background generation if it's actively running. +// The Recent generation progress being made will be saved before returning. +func (g *generator) stop() { + if !g.running { + log.Debug("Snapshot generation is not running") + return + } + ch := make(chan struct{}) + g.abort <- ch + <-ch + g.running = false +} + +// completed returns the flag indicating if the whole generation is done. +func (g *generator) completed() bool { + progress := g.progressMarker() + return progress == nil +} + +// progressMarker returns the current generation progress marker. It may slightly +// lag behind the actual generation position, as the progress field is only updated +// when checkAndFlush is called. The only effect is that some generated states +// may be refused for serving. +func (g *generator) progressMarker() []byte { + g.lock.RLock() + defer g.lock.RUnlock() + + return g.progress +} + +// splitMarker is an internal helper which splits the generation progress marker +// into two parts. +func splitMarker(marker []byte) ([]byte, []byte) { + var accMarker []byte + if len(marker) > 0 { + accMarker = marker[:common.HashLength] + } + return accMarker, marker +} + +// generateSnapshot regenerates a brand-new snapshot based on an existing state +// database and head block asynchronously. The snapshot is returned immediately +// and generation is continued in the background until done. +func generateSnapshot(triedb *Database, root common.Hash, noBuild bool) *diskLayer { + // Create a new disk layer with an initialized state marker at zero + var ( + stats = &generatorStats{start: time.Now()} + genMarker = []byte{} // Initialized but empty! + ) + dl := newDiskLayer(root, 0, triedb, nil, nil, newBuffer(triedb.config.WriteBufferSize, nil, nil, 0)) + dl.setGenerator(newGenerator(triedb.diskdb, noBuild, genMarker, stats)) + + if !noBuild { + dl.generator.run(root) + log.Info("Started snapshot generation", "root", root) + } + return dl +} + +// journalProgress persists the generator stats into the database to resume later. +func journalProgress(db ethdb.KeyValueWriter, marker []byte, stats *generatorStats) { + // Write out the generator marker. Note it's a standalone disk layer generator + // which is not mixed with journal. It's ok if the generator is persisted while + // journal is not. + entry := journalGenerator{ + Done: marker == nil, + Marker: marker, + } + if stats != nil { + entry.Accounts = stats.accounts + entry.Slots = stats.slots + entry.Storage = uint64(stats.storage) + } + blob, err := rlp.EncodeToBytes(entry) + if err != nil { + panic(err) // Cannot happen, here to catch dev errors + } + var logstr string + switch { + case marker == nil: + logstr = "done" + case bytes.Equal(marker, []byte{}): + logstr = "empty" + case len(marker) == common.HashLength: + logstr = fmt.Sprintf("%#x", marker) + default: + logstr = fmt.Sprintf("%#x:%#x", marker[:common.HashLength], marker[common.HashLength:]) + } + log.Debug("Journalled generator progress", "progress", logstr) + rawdb.WriteSnapshotGenerator(db, blob) +} + +// proofResult contains the output of range proving which can be used +// for further processing regardless if it is successful or not. +type proofResult struct { + keys [][]byte // The key set of all elements being iterated, even proving is failed + vals [][]byte // The val set of all elements being iterated, even proving is failed + diskMore bool // Set when the database has extra snapshot states since last iteration + trieMore bool // Set when the trie has extra snapshot states(only meaningful for successful proving) + proofErr error // Indicator whether the given state range is valid or not + tr *trie.Trie // The trie, in case the trie was resolved by the prover (may be nil) +} + +// valid returns the indicator that range proof is successful or not. +func (result *proofResult) valid() bool { + return result.proofErr == nil +} + +// last returns the last verified element key regardless of whether the range proof is +// successful or not. Nil is returned if nothing involved in the proving. +func (result *proofResult) last() []byte { + var last []byte + if len(result.keys) > 0 { + last = result.keys[len(result.keys)-1] + } + return last +} + +// forEach iterates all the visited elements and applies the given callback on them. +// The iteration is aborted if the callback returns non-nil error. +func (result *proofResult) forEach(callback func(key []byte, val []byte) error) error { + for i := 0; i < len(result.keys); i++ { + key, val := result.keys[i], result.vals[i] + if err := callback(key, val); err != nil { + return err + } + } + return nil +} + +// proveRange proves the snapshot segment with particular prefix is "valid". +// The iteration start point will be assigned if the iterator is restored from +// the last interruption. Max will be assigned in order to limit the maximum +// amount of data involved in each iteration. +// +// The proof result will be returned if the range proving is finished, otherwise +// the error will be returned to abort the entire procedure. +func (g *generator) proveRange(ctx *generatorContext, trieId *trie.ID, prefix []byte, kind string, origin []byte, max int, valueConvertFn func([]byte) ([]byte, error)) (*proofResult, error) { + var ( + keys [][]byte + vals [][]byte + proof = rawdb.NewMemoryDatabase() + diskMore = false + iter = ctx.iterator(kind) + start = time.Now() + min = append(prefix, origin...) + ) + for iter.Next() { + // Ensure the iterated item is always equal or larger than the given origin. + key := iter.Key() + if bytes.Compare(key, min) < 0 { + return nil, errors.New("invalid iteration position") + } + // Ensure the iterated item still fall in the specified prefix. If + // not which means the items in the specified area are all visited. + // Move the iterator a step back since we iterate one extra element + // out. + if !bytes.Equal(key[:len(prefix)], prefix) { + iter.Hold() + break + } + // Break if we've reached the max size, and signal that we're not + // done yet. Move the iterator a step back since we iterate one + // extra element out. + if len(keys) == max { + iter.Hold() + diskMore = true + break + } + keys = append(keys, common.CopyBytes(key[len(prefix):])) + + if valueConvertFn == nil { + vals = append(vals, common.CopyBytes(iter.Value())) + } else { + val, err := valueConvertFn(iter.Value()) + if err != nil { + // Special case, the state data is corrupted (invalid slim-format account), + // don't abort the entire procedure directly. Instead, let the fallback + // generation to heal the invalid data. + // + // Here append the original value to ensure that the number of key and + // value are aligned. + vals = append(vals, common.CopyBytes(iter.Value())) + log.Error("Failed to convert account state data", "err", err) + } else { + vals = append(vals, val) + } + } + } + // Update metrics for database iteration and merkle proving + if kind == snapStorage { + storageSnapReadCounter.Inc(time.Since(start).Nanoseconds()) + } else { + accountSnapReadCounter.Inc(time.Since(start).Nanoseconds()) + } + defer func(start time.Time) { + if kind == snapStorage { + storageProveCounter.Inc(time.Since(start).Nanoseconds()) + } else { + accountProveCounter.Inc(time.Since(start).Nanoseconds()) + } + }(time.Now()) + + // The snap state is exhausted, pass the entire key/val set for verification + root := trieId.Root + if origin == nil && !diskMore { + stackTr := trie.NewStackTrie(nil) + for i, key := range keys { + if err := stackTr.Update(key, vals[i]); err != nil { + return nil, err + } + } + if gotRoot := stackTr.Hash(); gotRoot != root { + return &proofResult{ + keys: keys, + vals: vals, + proofErr: fmt.Errorf("wrong root: have %#x want %#x", gotRoot, root), + }, nil + } + return &proofResult{keys: keys, vals: vals}, nil + } + // Snap state is chunked, generate edge proofs for verification. + tr, err := trie.New(trieId, &diskStore{db: g.db}) + if err != nil { + log.Info("Trie missing, snapshotting paused", "state", ctx.root, "kind", kind, "root", trieId.Root) + return nil, errMissingTrie + } + // Generate the Merkle proofs for the first and last element + if origin == nil { + origin = common.Hash{}.Bytes() + } + if err := tr.Prove(origin, proof); err != nil { + log.Debug("Failed to prove range", "kind", kind, "origin", origin, "err", err) + return &proofResult{ + keys: keys, + vals: vals, + diskMore: diskMore, + proofErr: err, + tr: tr, + }, nil + } + if len(keys) > 0 { + if err := tr.Prove(keys[len(keys)-1], proof); err != nil { + log.Debug("Failed to prove range", "kind", kind, "last", keys[len(keys)-1], "err", err) + return &proofResult{ + keys: keys, + vals: vals, + diskMore: diskMore, + proofErr: err, + tr: tr, + }, nil + } + } + // Verify the snapshot segment with range prover, ensure that all flat states + // in this range correspond to merkle trie. + cont, err := trie.VerifyRangeProof(root, origin, keys, vals, proof) + return &proofResult{ + keys: keys, + vals: vals, + diskMore: diskMore, + trieMore: cont, + proofErr: err, + tr: tr}, + nil +} + +// onStateCallback is a function that is called by generateRange, when processing a range of +// accounts or storage slots. For each element, the callback is invoked. +// +// - If 'delete' is true, then this element (and potential slots) needs to be deleted from the snapshot. +// - If 'write' is true, then this element needs to be updated with the 'val'. +// - If 'write' is false, then this element is already correct, and needs no update. +// The 'val' is the canonical encoding of the value (not the slim format for accounts) +// +// However, for accounts, the storage trie of the account needs to be checked. Also, +// dangling storages(storage exists but the corresponding account is missing) need to +// be cleaned up. +type onStateCallback func(key []byte, val []byte, write bool, delete bool) error + +// generateRange generates the state segment with particular prefix. Generation can +// either verify the correctness of existing state through range-proof and skip +// generation, or iterate trie to regenerate state on demand. +func (g *generator) generateRange(ctx *generatorContext, trieId *trie.ID, prefix []byte, kind string, origin []byte, max int, onState onStateCallback, valueConvertFn func([]byte) ([]byte, error)) (bool, []byte, error) { + // Use range prover to check the validity of the flat state in the range + result, err := g.proveRange(ctx, trieId, prefix, kind, origin, max, valueConvertFn) + if err != nil { + return false, nil, err + } + last := result.last() + + // Construct contextual logger + logCtx := []interface{}{"kind", kind, "prefix", hexutil.Encode(prefix)} + if len(origin) > 0 { + logCtx = append(logCtx, "origin", hexutil.Encode(origin)) + } + logger := log.New(logCtx...) + + // The range prover says the range is correct, skip trie iteration + if result.valid() { + successfulRangeProofMeter.Mark(1) + logger.Trace("Proved state range", "last", hexutil.Encode(last)) + + // The verification is passed, process each state with the given + // callback function. If this state represents a contract, the + // corresponding storage check will be performed in the callback + if err := result.forEach(func(key []byte, val []byte) error { return onState(key, val, false, false) }); err != nil { + return false, nil, err + } + // Only abort the iteration when both database and trie are exhausted + return !result.diskMore && !result.trieMore, last, nil + } + logger.Trace("Detected outdated state range", "last", hexutil.Encode(last), "err", result.proofErr) + failedRangeProofMeter.Mark(1) + + // Special case, the entire trie is missing. In the original trie scheme, + // all the duplicated subtries will be filtered out (only one copy of data + // will be stored). While in the snapshot model, all the storage tries + // belong to different contracts will be kept even they are duplicated. + // Track it to a certain extent remove the noise data used for statistics. + if origin == nil && last == nil { + meter := missallAccountMeter + if kind == snapStorage { + meter = missallStorageMeter + } + meter.Mark(1) + } + // We use the snap data to build up a cache which can be used by the + // main account trie as a primary lookup when resolving hashes + var resolver trie.NodeResolver + if len(result.keys) > 0 { + tr := trie.NewEmpty(nil) + for i, key := range result.keys { + tr.Update(key, result.vals[i]) + } + _, nodes := tr.Commit(false) + hashSet := nodes.HashSet() + resolver = func(owner common.Hash, path []byte, hash common.Hash) []byte { + return hashSet[hash] + } + } + // Construct the trie for state iteration, reuse the trie + // if it's already opened with some nodes resolved. + tr := result.tr + if tr == nil { + tr, err = trie.New(trieId, &diskStore{db: g.db}) + if err != nil { + log.Info("Trie missing, snapshotting paused", "state", ctx.root, "kind", kind, "root", trieId.Root) + return false, nil, errMissingTrie + } + } + var ( + trieMore bool + kvkeys, kvvals = result.keys, result.vals + + // counters + count = 0 // number of states delivered by iterator + created = 0 // states created from the trie + updated = 0 // states updated from the trie + deleted = 0 // states not in trie, but were in snapshot + untouched = 0 // states already correct + + // timers + start = time.Now() + internal time.Duration + ) + nodeIt, err := tr.NodeIterator(origin) + if err != nil { + return false, nil, err + } + nodeIt.AddResolver(resolver) + iter := trie.NewIterator(nodeIt) + + for iter.Next() { + if last != nil && bytes.Compare(iter.Key, last) > 0 { + trieMore = true + break + } + count++ + write := true + created++ + for len(kvkeys) > 0 { + if cmp := bytes.Compare(kvkeys[0], iter.Key); cmp < 0 { + // delete the key + istart := time.Now() + if err := onState(kvkeys[0], nil, false, true); err != nil { + return false, nil, err + } + kvkeys = kvkeys[1:] + kvvals = kvvals[1:] + deleted++ + internal += time.Since(istart) + continue + } else if cmp == 0 { + // the snapshot key can be overwritten + created-- + if write = !bytes.Equal(kvvals[0], iter.Value); write { + updated++ + } else { + untouched++ + } + kvkeys = kvkeys[1:] + kvvals = kvvals[1:] + } + break + } + istart := time.Now() + if err := onState(iter.Key, iter.Value, write, false); err != nil { + return false, nil, err + } + internal += time.Since(istart) + } + if iter.Err != nil { + // Trie errors should never happen. Still, in case of a bug, expose the + // error here, as the outer code will presume errors are interrupts, not + // some deeper issues. + log.Error("State snapshotter failed to iterate trie", "err", iter.Err) + return false, nil, iter.Err + } + // Delete all stale snapshot states remaining + istart := time.Now() + for _, key := range kvkeys { + if err := onState(key, nil, false, true); err != nil { + return false, nil, err + } + deleted += 1 + } + internal += time.Since(istart) + + // Update metrics for counting trie iteration + if kind == snapStorage { + storageTrieReadCounter.Inc((time.Since(start) - internal).Nanoseconds()) + } else { + accountTrieReadCounter.Inc((time.Since(start) - internal).Nanoseconds()) + } + logger.Trace("Regenerated state range", "root", trieId.Root, "last", hexutil.Encode(last), + "count", count, "created", created, "updated", updated, "untouched", untouched, "deleted", deleted) + + // If there are either more trie items, or there are more snap items + // (in the next segment), then we need to keep working + return !trieMore && !result.diskMore, last, nil +} + +// checkAndFlush checks if an interruption signal is received or the +// batch size has exceeded the allowance. +func (g *generator) checkAndFlush(ctx *generatorContext, current []byte) error { + var abort chan struct{} + select { + case abort = <-g.abort: + default: + } + if ctx.batch.ValueSize() > ethdb.IdealBatchSize || abort != nil { + if bytes.Compare(current, g.progress) < 0 { + log.Error("Snapshot generator went backwards", "current", fmt.Sprintf("%x", current), "genMarker", fmt.Sprintf("%x", g.progress)) + } + // Persist the progress marker regardless of whether the batch is empty or not. + // It may happen that all the flat states in the database are correct, so the + // generator indeed makes progress even if there is nothing to commit. + journalProgress(ctx.batch, current, g.stats) + + // Flush out the database writes atomically + if err := ctx.batch.Write(); err != nil { + return err + } + ctx.batch.Reset() + + // Update the generation progress marker + g.lock.Lock() + g.progress = current + g.lock.Unlock() + + // Abort the generation if it's required + if abort != nil { + g.stats.log("Aborting snapshot generation", ctx.root, g.progress) + return newAbortErr(abort) // bubble up an error for interruption + } + // Don't hold the iterators too long, release them to let compactor works + ctx.reopenIterator(snapAccount) + ctx.reopenIterator(snapStorage) + } + if time.Since(ctx.logged) > 8*time.Second { + g.stats.log("Generating snapshot", ctx.root, g.progress) + ctx.logged = time.Now() + } + return nil +} + +// generateStorages generates the missing storage slots of the specific contract. +// It's supposed to restart the generation from the given origin position. +func (g *generator) generateStorages(ctx *generatorContext, account common.Hash, storageRoot common.Hash, storeMarker []byte) error { + onStorage := func(key []byte, val []byte, write bool, delete bool) error { + defer func(start time.Time) { + storageWriteCounter.Inc(time.Since(start).Nanoseconds()) + }(time.Now()) + + if delete { + rawdb.DeleteStorageSnapshot(ctx.batch, account, common.BytesToHash(key)) + wipedStorageMeter.Mark(1) + return nil + } + if write { + rawdb.WriteStorageSnapshot(ctx.batch, account, common.BytesToHash(key), val) + generatedStorageMeter.Mark(1) + } else { + recoveredStorageMeter.Mark(1) + } + g.stats.storage += common.StorageSize(1 + 2*common.HashLength + len(val)) + g.stats.slots++ + + // If we've exceeded our batch allowance or termination was requested, flush to disk + if err := g.checkAndFlush(ctx, append(account[:], key...)); err != nil { + return err + } + return nil + } + // Loop for re-generating the missing storage slots. + var origin = common.CopyBytes(storeMarker) + for { + id := trie.StorageTrieID(ctx.root, account, storageRoot) + exhausted, last, err := g.generateRange(ctx, id, append(rawdb.SnapshotStoragePrefix, account.Bytes()...), snapStorage, origin, storageCheckRange, onStorage, nil) + if err != nil { + return err // The procedure it aborted, either by external signal or internal error. + } + // Abort the procedure if the entire contract storage is generated + if exhausted { + break + } + if origin = increaseKey(last); origin == nil { + break // special case, the last is 0xffffffff...fff + } + } + return nil +} + +// generateAccounts generates the missing snapshot accounts as well as their +// storage slots in the main trie. It's supposed to restart the generation +// from the given origin position. +func (g *generator) generateAccounts(ctx *generatorContext, accMarker []byte) error { + onAccount := func(key []byte, val []byte, write bool, delete bool) error { + // Make sure to clear all dangling storages before this account + account := common.BytesToHash(key) + g.stats.dangling += ctx.removeStorageBefore(account) + + start := time.Now() + if delete { + rawdb.DeleteAccountSnapshot(ctx.batch, account) + wipedAccountMeter.Mark(1) + accountWriteCounter.Inc(time.Since(start).Nanoseconds()) + + ctx.removeStorageAt(account) + return nil + } + // Retrieve the current account and flatten it into the internal format + var acc types.StateAccount + if err := rlp.DecodeBytes(val, &acc); err != nil { + log.Crit("Invalid account encountered during snapshot creation", "err", err) + } + // If the account is not yet in-progress, write it out + if accMarker == nil || !bytes.Equal(account[:], accMarker) { + dataLen := len(val) // Approximate size, saves us a round of RLP-encoding + if !write { + if bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) { + dataLen -= 32 + } + if acc.Root == types.EmptyRootHash { + dataLen -= 32 + } + recoveredAccountMeter.Mark(1) + } else { + data := types.SlimAccountRLP(acc) + dataLen = len(data) + rawdb.WriteAccountSnapshot(ctx.batch, account, data) + generatedAccountMeter.Mark(1) + } + g.stats.storage += common.StorageSize(1 + common.HashLength + dataLen) + g.stats.accounts++ + } + // If the snap generation goes here after interrupted, genMarker may go backward + // when last genMarker is consisted of accountHash and storageHash + marker := account[:] + if accMarker != nil && bytes.Equal(marker, accMarker) && len(g.progress) > common.HashLength { + marker = g.progress + } + // If we've exceeded our batch allowance or termination was requested, flush to disk + if err := g.checkAndFlush(ctx, marker); err != nil { + return err + } + accountWriteCounter.Inc(time.Since(start).Nanoseconds()) // let's count flush time as well + + // If the iterated account is the contract, create a further loop to + // verify or regenerate the contract storage. + if acc.Root == types.EmptyRootHash { + ctx.removeStorageAt(account) + } else { + var storeMarker []byte + if accMarker != nil && bytes.Equal(account[:], accMarker) && len(g.progress) > common.HashLength { + storeMarker = g.progress[common.HashLength:] + } + if err := g.generateStorages(ctx, account, acc.Root, storeMarker); err != nil { + return err + } + } + // Some account processed, unmark the marker + accMarker = nil + return nil + } + origin := common.CopyBytes(accMarker) + for { + id := trie.StateTrieID(ctx.root) + exhausted, last, err := g.generateRange(ctx, id, rawdb.SnapshotAccountPrefix, snapAccount, origin, accountCheckRange, onAccount, types.FullAccountRLP) + if err != nil { + return err // The procedure it aborted, either by external signal or internal error. + } + origin = increaseKey(last) + + // Last step, cleanup the storages after the last account. + // All the left storages should be treated as dangling. + if origin == nil || exhausted { + g.stats.dangling += ctx.removeRemainingStorage() + break + } + } + return nil +} + +// generate is a background thread that iterates over the state and storage tries, +// constructing the state snapshot. All the arguments are purely for statistics +// gathering and logging, since the method surfs the blocks as they arrive, often +// being restarted. +func (g *generator) generate(ctx *generatorContext) { + g.stats.log("Resuming snapshot generation", ctx.root, g.progress) + defer ctx.close() + + // Persist the initial marker and state snapshot root if progress is none + if len(g.progress) == 0 { + batch := g.db.NewBatch() + rawdb.WriteSnapshotRoot(batch, ctx.root) + journalProgress(batch, g.progress, g.stats) + if err := batch.Write(); err != nil { + log.Crit("Failed to write initialized state marker", "err", err) + } + } + // Initialize the global generator context. The snapshot iterators are + // opened at the interrupted position because the assumption is held + // that all the snapshot data are generated correctly before the marker. + // Even if the snapshot data is updated during the interruption (before + // or at the marker), the assumption is still held. + // For the account or storage slot at the interruption, they will be + // processed twice by the generator(they are already processed in the + // last run) but it's fine. + var ( + accMarker, _ = splitMarker(g.progress) + abort chan struct{} + ) + if err := g.generateAccounts(ctx, accMarker); err != nil { + // Extract the received interruption signal if exists + var aerr *abortErr + if errors.As(err, &aerr) { + abort = aerr.abort + } + // Aborted by internal error, wait the signal + if abort == nil { + abort = <-g.abort + } + close(abort) + return + } + // Snapshot fully generated, set the marker to nil. + // Note even there is nothing to commit, persist the + // generator anyway to mark the snapshot is complete. + journalProgress(ctx.batch, nil, g.stats) + if err := ctx.batch.Write(); err != nil { + log.Error("Failed to flush batch", "err", err) + abort = <-g.abort + close(abort) + return + } + ctx.batch.Reset() + + log.Info("Generated snapshot", "accounts", g.stats.accounts, "slots", g.stats.slots, + "storage", g.stats.storage, "dangling", g.stats.dangling, "elapsed", common.PrettyDuration(time.Since(g.stats.start))) + + // Update the generation progress marker + g.lock.Lock() + g.progress = nil + g.lock.Unlock() + close(g.done) + + // Someone will be looking for us, wait it out + abort = <-g.abort + close(abort) +} + +// increaseKey increase the input key by one bit. Return nil if the entire +// addition operation overflows. +func increaseKey(key []byte) []byte { + for i := len(key) - 1; i >= 0; i-- { + key[i]++ + if key[i] != 0x0 { + return key + } + } + return nil +} + +// abortErr wraps an interruption signal received to represent the +// generation is aborted by external processes. +type abortErr struct { + abort chan struct{} +} + +func newAbortErr(abort chan struct{}) error { + return &abortErr{abort: abort} +} + +func (err *abortErr) Error() string { + return "aborted" +} diff --git a/triedb/pathdb/generate_test.go b/triedb/pathdb/generate_test.go new file mode 100644 index 0000000000..23efb0e3c5 --- /dev/null +++ b/triedb/pathdb/generate_test.go @@ -0,0 +1,766 @@ +// Copyright 2024 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 . + +package pathdb + +import ( + "fmt" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/internal/testrand" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" + "github.com/holiman/uint256" +) + +func hashData(input []byte) common.Hash { + return crypto.Keccak256Hash(input) +} + +type genTester struct { + diskdb ethdb.Database + db *Database + acctTrie *trie.Trie + nodes *trienode.MergedNodeSet + states *StateSetWithOrigin +} + +func newGenTester() *genTester { + disk := rawdb.NewMemoryDatabase() + config := *Defaults + config.SnapshotNoBuild = true // no background generation + db := New(disk, &config, false) + tr, _ := trie.New(trie.StateTrieID(types.EmptyRootHash), db) + return &genTester{ + diskdb: disk, + db: db, + acctTrie: tr, + nodes: trienode.NewMergedNodeSet(), + states: NewStateSetWithOrigin(nil, nil, nil, nil, false), + } +} + +func (t *genTester) addTrieAccount(acckey string, acc *types.StateAccount) { + var ( + addr = common.BytesToAddress([]byte(acckey)) + key = hashData([]byte(acckey)) + val, _ = rlp.EncodeToBytes(acc) + ) + t.acctTrie.MustUpdate(key.Bytes(), val) + + t.states.accountData[key] = val + t.states.accountOrigin[addr] = nil +} + +func (t *genTester) addSnapAccount(acckey string, acc *types.StateAccount) { + key := hashData([]byte(acckey)) + rawdb.WriteAccountSnapshot(t.diskdb, key, types.SlimAccountRLP(*acc)) +} + +func (t *genTester) addAccount(acckey string, acc *types.StateAccount) { + t.addTrieAccount(acckey, acc) + t.addSnapAccount(acckey, acc) +} + +func (t *genTester) addSnapStorage(accKey string, keys []string, vals []string) { + accHash := hashData([]byte(accKey)) + for i, key := range keys { + rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i])) + } +} + +func (t *genTester) makeStorageTrie(accKey string, keys []string, vals []string, commit bool) common.Hash { + var ( + owner = hashData([]byte(accKey)) + addr = common.BytesToAddress([]byte(accKey)) + id = trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash) + tr, _ = trie.New(id, t.db) + + storages = make(map[common.Hash][]byte) + storageOrigins = make(map[common.Hash][]byte) + ) + for i, k := range keys { + key := hashData([]byte(k)) + tr.MustUpdate(key.Bytes(), []byte(vals[i])) + storages[key] = []byte(vals[i]) + storageOrigins[key] = nil + } + if !commit { + return tr.Hash() + } + root, nodes := tr.Commit(false) + if nodes != nil { + t.nodes.Merge(nodes) + } + t.states.storageData[owner] = storages + t.states.storageOrigin[addr] = storageOrigins + return root +} + +func (t *genTester) Commit() common.Hash { + root, nodes := t.acctTrie.Commit(true) + if nodes != nil { + t.nodes.Merge(nodes) + } + t.db.Update(root, types.EmptyRootHash, 0, t.nodes, t.states) + t.db.Commit(root, false) + return root +} + +func (t *genTester) CommitAndGenerate() (common.Hash, *diskLayer) { + root := t.Commit() + dl := generateSnapshot(t.db, root, false) + return root, dl +} + +// Tests that snapshot generation from an empty database. +func TestGeneration(t *testing.T) { + helper := newGenTester() + stRoot := helper.makeStorageTrie("", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false) + + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + + helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + + root, dl := helper.CommitAndGenerate() + if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want { + t.Fatalf("have %#x want %#x", have, want) + } + select { + case <-dl.generator.done: + // Snapshot generation succeeded + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +// Tests that snapshot generation with existent flat state, where the flat state +// contains some errors: +// - the contract with empty storage root but has storage entries in the disk +// - the contract with non empty storage root but empty storage slots +// - the contract(non-empty storage) misses some storage slots +// - miss in the beginning +// - miss in the middle +// - miss in the end +// +// - the contract(non-empty storage) has wrong storage slots +// - wrong slots in the beginning +// - wrong slots in the middle +// - wrong slots in the end +// +// - the contract(non-empty storage) has extra storage slots +// - extra slots in the beginning +// - extra slots in the middle +// - extra slots in the end +func TestGenerateExistentStateWithWrongStorage(t *testing.T) { + helper := newGenTester() + + // Account one, empty storage trie root but non-empty flat states + helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + + // Account two, non-empty storage trie root but empty flat states + stRoot := helper.makeStorageTrie("acc-2", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + + // Miss slots + { + // Account three, non-empty root but misses slots in the beginning + helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) + + // Account four, non-empty root but misses slots in the middle + helper.makeStorageTrie("acc-4", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) + + // Account five, non-empty root but misses slots in the end + helper.makeStorageTrie("acc-5", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) + } + + // Wrong storage slots + { + // Account six, non-empty root but wrong slots in the beginning + helper.makeStorageTrie("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) + + // Account seven, non-empty root but wrong slots in the middle + helper.makeStorageTrie("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) + + // Account eight, non-empty root but wrong slots in the end + helper.makeStorageTrie("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-8", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) + + // Account 9, non-empty root but rotated slots + helper.makeStorageTrie("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-9", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) + } + + // Extra storage slots + { + // Account 10, non-empty root but extra slots in the beginning + helper.makeStorageTrie("acc-10", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-10", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) + + // Account 11, non-empty root but extra slots in the middle + helper.makeStorageTrie("acc-11", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-11", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) + + // Account 12, non-empty root but extra slots in the end + helper.makeStorageTrie("acc-12", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-12", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) + } + + root, dl := helper.CommitAndGenerate() + t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0 + + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +// Tests that snapshot generation with existent flat state, where the flat state +// contains some errors: +// - miss accounts +// - wrong accounts +// - extra accounts +func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { + helper := newGenTester() + + // Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6] + helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.makeStorageTrie("acc-2", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.makeStorageTrie("acc-4", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + stRoot := helper.makeStorageTrie("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + + // Missing accounts, only in the trie + { + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning + helper.addTrieAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle + helper.addTrieAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End + } + + // Wrong accounts + { + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) + + helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + } + + // Extra accounts, only in the snap + { + helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning + helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle + helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end + } + + root, dl := helper.CommitAndGenerate() + t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8 + + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateCorruptAccountTrie(t *testing.T) { + helper := newGenTester() + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 + + root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 + + // Delete an account trie node and ensure the generator chokes + path := []byte{0xc} + if !rawdb.HasAccountTrieNode(helper.diskdb, path) { + t.Logf("Invalid node path to delete, %v", path) + } + rawdb.DeleteAccountTrieNode(helper.diskdb, path) + helper.db.tree.bottom().resetCache() + + dl := generateSnapshot(helper.db, root, false) + select { + case <-dl.generator.done: + // Snapshot generation succeeded + t.Errorf("Snapshot generated against corrupt account trie") + + case <-time.After(time.Second): + // Not generated fast enough, hopefully blocked inside on missing trie node fail + } + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateMissingStorageTrie(t *testing.T) { + var ( + acc1 = hashData([]byte("acc-1")) + acc3 = hashData([]byte("acc-3")) + helper = newGenTester() + ) + stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 + + root := helper.Commit() + + // Delete storage trie root of account one and three. + rawdb.DeleteStorageTrieNode(helper.diskdb, acc1, nil) + rawdb.DeleteStorageTrieNode(helper.diskdb, acc3, nil) + helper.db.tree.bottom().resetCache() + + dl := generateSnapshot(helper.db, root, false) + select { + case <-dl.generator.done: + // Snapshot generation succeeded + t.Errorf("Snapshot generated against corrupt storage trie") + + case <-time.After(time.Second): + // Not generated fast enough, hopefully blocked inside on missing trie node fail + } + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateCorruptStorageTrie(t *testing.T) { + helper := newGenTester() + + stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 + + root := helper.Commit() + + // Delete a node in the storage trie. + path := []byte{0x4} + if !rawdb.HasStorageTrieNode(helper.diskdb, hashData([]byte("acc-1")), path) { + t.Logf("Invalid node path to delete, %v", path) + } + rawdb.DeleteStorageTrieNode(helper.diskdb, hashData([]byte("acc-1")), []byte{0x4}) + + if !rawdb.HasStorageTrieNode(helper.diskdb, hashData([]byte("acc-3")), path) { + t.Logf("Invalid node path to delete, %v", path) + } + rawdb.DeleteStorageTrieNode(helper.diskdb, hashData([]byte("acc-3")), []byte{0x4}) + + helper.db.tree.bottom().resetCache() + + dl := generateSnapshot(helper.db, root, false) + select { + case <-dl.generator.done: + // Snapshot generation succeeded + t.Errorf("Snapshot generated against corrupt storage trie") + + case <-time.After(time.Second): + // Not generated fast enough, hopefully blocked inside on missing trie node fail + } + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateWithExtraAccounts(t *testing.T) { + helper := newGenTester() + + // Account one in the trie + stRoot := helper.makeStorageTrie("acc-1", + []string{"key-1", "key-2", "key-3", "key-4", "key-5"}, + []string{"val-1", "val-2", "val-3", "val-4", "val-5"}, + true, + ) + acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} + val, _ := rlp.EncodeToBytes(acc) + helper.acctTrie.MustUpdate(hashData([]byte("acc-1")).Bytes(), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + + // Identical in the snap + key := hashData([]byte("acc-1")) + rawdb.WriteAccountSnapshot(helper.diskdb, key, val) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-4")), []byte("val-4")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-5")), []byte("val-5")) + + // Account two exists only in the snapshot + stRoot = helper.makeStorageTrie("acc-2", + []string{"key-1", "key-2", "key-3", "key-4", "key-5"}, + []string{"val-1", "val-2", "val-3", "val-4", "val-5"}, + true, + ) + acc = &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} + val, _ = rlp.EncodeToBytes(acc) + key = hashData([]byte("acc-2")) + rawdb.WriteAccountSnapshot(helper.diskdb, key, val) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3")) + + root := helper.Commit() + + // To verify the test: If we now inspect the snap db, there should exist extraneous storage items + if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { + t.Fatalf("expected snap storage to exist") + } + dl := generateSnapshot(helper.db, root, false) + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() + + // If we now inspect the snap db, there should exist no extraneous storage items + if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { + t.Fatalf("expected slot to be removed, got %v", string(data)) + } +} + +func TestGenerateWithManyExtraAccounts(t *testing.T) { + helper := newGenTester() + + // Account one in the trie + stRoot := helper.makeStorageTrie("acc-1", + []string{"key-1", "key-2", "key-3"}, + []string{"val-1", "val-2", "val-3"}, + true, + ) + acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} + val, _ := rlp.EncodeToBytes(acc) + helper.acctTrie.MustUpdate(hashData([]byte("acc-1")).Bytes(), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + + // Identical in the snap + key := hashData([]byte("acc-1")) + rawdb.WriteAccountSnapshot(helper.diskdb, key, val) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3")) + + // 100 accounts exist only in snapshot + for i := 0; i < 1000; i++ { + acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} + val, _ := rlp.EncodeToBytes(acc) + key := hashData([]byte(fmt.Sprintf("acc-%d", i))) + rawdb.WriteAccountSnapshot(helper.diskdb, key, val) + } + + _, dl := helper.CommitAndGenerate() + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateWithExtraBeforeAndAfter(t *testing.T) { + helper := newGenTester() + + acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} + val, _ := rlp.EncodeToBytes(acc) + + acctHashA := hashData([]byte("acc-1")) + acctHashB := hashData([]byte("acc-2")) + + helper.acctTrie.MustUpdate(acctHashA.Bytes(), val) + helper.acctTrie.MustUpdate(acctHashB.Bytes(), val) + + rawdb.WriteAccountSnapshot(helper.diskdb, acctHashA, val) + rawdb.WriteAccountSnapshot(helper.diskdb, acctHashB, val) + + for i := 0; i < 16; i++ { + rawdb.WriteAccountSnapshot(helper.diskdb, common.Hash{byte(i)}, val) + } + _, dl := helper.CommitAndGenerate() + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateWithMalformedStateData(t *testing.T) { + helper := newGenTester() + + acctHash := hashData([]byte("acc")) + acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} + val, _ := rlp.EncodeToBytes(acc) + helper.acctTrie.MustUpdate(acctHash.Bytes(), val) + + junk := make([]byte, 100) + copy(junk, []byte{0xde, 0xad}) + rawdb.WriteAccountSnapshot(helper.diskdb, acctHash, junk) + for i := 0; i < 16; i++ { + rawdb.WriteAccountSnapshot(helper.diskdb, common.Hash{byte(i)}, junk) + } + + _, dl := helper.CommitAndGenerate() + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateFromEmptySnap(t *testing.T) { + helper := newGenTester() + + for i := 0; i < 400; i++ { + stRoot := helper.makeStorageTrie(fmt.Sprintf("acc-%d", i), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addTrieAccount(fmt.Sprintf("acc-%d", i), &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + } + root, snap := helper.CommitAndGenerate() + t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4 + + select { + case <-snap.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + snap.generator.stop() +} + +func TestGenerateWithIncompleteStorage(t *testing.T) { + helper := newGenTester() + stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"} + stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"} + + // We add 8 accounts, each one is missing exactly one of the storage slots. This means + // we don't have to order the keys and figure out exactly which hash-key winds up + // on the sensitive spots at the boundaries + for i := 0; i < 8; i++ { + accKey := fmt.Sprintf("acc-%d", i) + stRoot := helper.makeStorageTrie(accKey, stKeys, stVals, true) + helper.addAccount(accKey, &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + var moddedKeys []string + var moddedVals []string + for ii := 0; ii < 8; ii++ { + if ii != i { + moddedKeys = append(moddedKeys, stKeys[ii]) + moddedVals = append(moddedVals, stVals[ii]) + } + } + helper.addSnapStorage(accKey, moddedKeys, moddedVals) + } + root, dl := helper.CommitAndGenerate() + t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff + + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func incKey(key []byte) []byte { + for i := len(key) - 1; i >= 0; i-- { + key[i]++ + if key[i] != 0x0 { + break + } + } + return key +} + +func decKey(key []byte) []byte { + for i := len(key) - 1; i >= 0; i-- { + key[i]-- + if key[i] != 0xff { + break + } + } + return key +} + +func populateDangling(disk ethdb.KeyValueStore) { + populate := func(accountHash common.Hash, keys []string, vals []string) { + for i, key := range keys { + rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i])) + } + } + // Dangling storages of the "first" account + populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + + // Dangling storages of the "last" account + populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + + // Dangling storages around the account 1 + hash := decKey(hashData([]byte("acc-1")).Bytes()) + populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + hash = incKey(hashData([]byte("acc-1")).Bytes()) + populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + + // Dangling storages around the account 2 + hash = decKey(hashData([]byte("acc-2")).Bytes()) + populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + hash = incKey(hashData([]byte("acc-2")).Bytes()) + populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + + // Dangling storages around the account 3 + hash = decKey(hashData([]byte("acc-3")).Bytes()) + populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + hash = incKey(hashData([]byte("acc-3")).Bytes()) + populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + + // Dangling storages of the random account + populate(testrand.Hash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + populate(testrand.Hash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + populate(testrand.Hash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) +} + +func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { + var helper = newGenTester() + + stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + + helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + + helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) + + populateDangling(helper.diskdb) + + _, dl := helper.CommitAndGenerate() + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} + +func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { + var helper = newGenTester() + + stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + + helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) + helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + + populateDangling(helper.diskdb) + + _, dl := helper.CommitAndGenerate() + select { + case <-dl.generator.done: + // Snapshot generation succeeded + + case <-time.After(3 * time.Second): + t.Errorf("Snapshot generation failed") + } + // TODO(rjl493456442) enable the snapshot tests + // checkSnapRoot(t, snap, root) + + // Signal abortion to the generator and wait for it to tear down + dl.generator.stop() +} diff --git a/triedb/pathdb/iterator.go b/triedb/pathdb/iterator.go index 980f228cf5..84ea08ddd3 100644 --- a/triedb/pathdb/iterator.go +++ b/triedb/pathdb/iterator.go @@ -91,15 +91,14 @@ type diffAccountIterator struct { } // newDiffAccountIterator creates an account iterator over the given state set. -func newDiffAccountIterator(seek common.Hash, states *stateSet, fn loadAccount) AccountIterator { +func newDiffAccountIterator(seek common.Hash, accountList []common.Hash, fn loadAccount) AccountIterator { // Seek out the requested starting account - hashes := states.accountList() - index := sort.Search(len(hashes), func(i int) bool { - return bytes.Compare(seek[:], hashes[i][:]) <= 0 + index := sort.Search(len(accountList), func(i int) bool { + return bytes.Compare(seek[:], accountList[i][:]) <= 0 }) // Assemble and returned the already seeked iterator return &diffAccountIterator{ - keys: hashes[index:], + keys: accountList[index:], loadFn: fn, } } @@ -236,15 +235,14 @@ type diffStorageIterator struct { } // newDiffStorageIterator creates a storage iterator over a single diff layer. -func newDiffStorageIterator(account common.Hash, seek common.Hash, states *stateSet, fn loadStorage) StorageIterator { - hashes := states.storageList(account) - index := sort.Search(len(hashes), func(i int) bool { - return bytes.Compare(seek[:], hashes[i][:]) <= 0 +func newDiffStorageIterator(account common.Hash, seek common.Hash, storageList []common.Hash, fn loadStorage) StorageIterator { + index := sort.Search(len(storageList), func(i int) bool { + return bytes.Compare(seek[:], storageList[i][:]) <= 0 }) // Assemble and returned the already seeked iterator return &diffStorageIterator{ account: account, - keys: hashes[index:], + keys: storageList[index:], loadFn: fn, } } diff --git a/triedb/pathdb/iterator_binary.go b/triedb/pathdb/iterator_binary.go index dec31e8f3f..0620081d0c 100644 --- a/triedb/pathdb/iterator_binary.go +++ b/triedb/pathdb/iterator_binary.go @@ -45,6 +45,12 @@ type binaryIterator struct { // accounts in a slow, but easily verifiable way. Note this function is used // for initialization, use `newBinaryAccountIterator` as the API. func (dl *diskLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator { + // The state set in the disk layer is mutable, hold the lock before obtaining + // the account list to prevent concurrent map iteration and write. + dl.lock.RLock() + accountList := dl.buffer.states.accountList() + dl.lock.RUnlock() + // Create two iterators for state buffer and the persistent state in disk // respectively and combine them as a binary iterator. l := &binaryIterator{ @@ -54,7 +60,7 @@ func (dl *diskLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator // The account key list for iteration is deterministic once the iterator // is constructed, no matter the referenced disk layer is stale or not // later. - a: newDiffAccountIterator(seek, dl.buffer.states, nil), + a: newDiffAccountIterator(seek, accountList, nil), b: newDiskAccountIterator(dl.db.diskdb, seek), } l.aDone = !l.a.Next() @@ -68,6 +74,9 @@ func (dl *diskLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator func (dl *diffLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator { parent, ok := dl.parent.(*diffLayer) if !ok { + // The state set in diff layer is immutable and will never be stale, + // so the read lock protection is unnecessary. + accountList := dl.states.stateSet.accountList() l := &binaryIterator{ // The account loader function is unnecessary; the account key list // produced by the supplied state set alone is sufficient for iteration. @@ -75,13 +84,16 @@ func (dl *diffLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator // The account key list for iteration is deterministic once the iterator // is constructed, no matter the referenced disk layer is stale or not // later. - a: newDiffAccountIterator(seek, dl.states.stateSet, nil), + a: newDiffAccountIterator(seek, accountList, nil), b: dl.parent.(*diskLayer).initBinaryAccountIterator(seek), } l.aDone = !l.a.Next() l.bDone = !l.b.Next() return l } + // The state set in diff layer is immutable and will never be stale, + // so the read lock protection is unnecessary. + accountList := dl.states.stateSet.accountList() l := &binaryIterator{ // The account loader function is unnecessary; the account key list // produced by the supplied state set alone is sufficient for iteration. @@ -89,7 +101,7 @@ func (dl *diffLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator // The account key list for iteration is deterministic once the iterator // is constructed, no matter the referenced disk layer is stale or not // later. - a: newDiffAccountIterator(seek, dl.states.stateSet, nil), + a: newDiffAccountIterator(seek, accountList, nil), b: parent.initBinaryAccountIterator(seek), } l.aDone = !l.a.Next() @@ -101,6 +113,12 @@ func (dl *diffLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator // storage slots in a slow, but easily verifiable way. Note this function is used // for initialization, use `newBinaryStorageIterator` as the API. func (dl *diskLayer) initBinaryStorageIterator(account common.Hash, seek common.Hash) *binaryIterator { + // The state set in the disk layer is mutable, hold the lock before obtaining + // the storage list to prevent concurrent map iteration and write. + dl.lock.RLock() + storageList := dl.buffer.states.storageList(account) + dl.lock.RUnlock() + // Create two iterators for state buffer and the persistent state in disk // respectively and combine them as a binary iterator. l := &binaryIterator{ @@ -110,7 +128,7 @@ func (dl *diskLayer) initBinaryStorageIterator(account common.Hash, seek common. // The storage key list for iteration is deterministic once the iterator // is constructed, no matter the referenced disk layer is stale or not // later. - a: newDiffStorageIterator(account, seek, dl.buffer.states, nil), + a: newDiffStorageIterator(account, seek, storageList, nil), b: newDiskStorageIterator(dl.db.diskdb, account, seek), } l.aDone = !l.a.Next() @@ -124,6 +142,9 @@ func (dl *diskLayer) initBinaryStorageIterator(account common.Hash, seek common. func (dl *diffLayer) initBinaryStorageIterator(account common.Hash, seek common.Hash) *binaryIterator { parent, ok := dl.parent.(*diffLayer) if !ok { + // The state set in diff layer is immutable and will never be stale, + // so the read lock protection is unnecessary. + storageList := dl.states.stateSet.storageList(account) l := &binaryIterator{ // The storage loader function is unnecessary; the storage key list // produced by the supplied state set alone is sufficient for iteration. @@ -131,13 +152,16 @@ func (dl *diffLayer) initBinaryStorageIterator(account common.Hash, seek common. // The storage key list for iteration is deterministic once the iterator // is constructed, no matter the referenced disk layer is stale or not // later. - a: newDiffStorageIterator(account, seek, dl.states.stateSet, nil), + a: newDiffStorageIterator(account, seek, storageList, nil), b: dl.parent.(*diskLayer).initBinaryStorageIterator(account, seek), } l.aDone = !l.a.Next() l.bDone = !l.b.Next() return l } + // The state set in diff layer is immutable and will never be stale, + // so the read lock protection is unnecessary. + storageList := dl.states.stateSet.storageList(account) l := &binaryIterator{ // The storage loader function is unnecessary; the storage key list // produced by the supplied state set alone is sufficient for iteration. @@ -145,7 +169,7 @@ func (dl *diffLayer) initBinaryStorageIterator(account common.Hash, seek common. // The storage key list for iteration is deterministic once the iterator // is constructed, no matter the referenced disk layer is stale or not // later. - a: newDiffStorageIterator(account, seek, dl.states.stateSet, nil), + a: newDiffStorageIterator(account, seek, storageList, nil), b: parent.initBinaryStorageIterator(account, seek), } l.aDone = !l.a.Next() diff --git a/triedb/pathdb/iterator_fast.go b/triedb/pathdb/iterator_fast.go index 966e37a7cb..87b2dd567a 100644 --- a/triedb/pathdb/iterator_fast.go +++ b/triedb/pathdb/iterator_fast.go @@ -76,11 +76,17 @@ func newFastIterator(db *Database, root common.Hash, account common.Hash, seek c if accountIterator { switch dl := current.(type) { case *diskLayer: + // The state set in the disk layer is mutable, hold the lock before obtaining + // the account list to prevent concurrent map iteration and write. + dl.lock.RLock() + accountList := dl.buffer.states.accountList() + dl.lock.RUnlock() + fi.iterators = append(fi.iterators, &weightedIterator{ // The state set in the disk layer is mutable, and the entire state becomes stale // if a diff layer above is merged into it. Therefore, staleness must be checked, // and the storage slot should be retrieved with read lock protection. - it: newDiffAccountIterator(seek, dl.buffer.states, func(hash common.Hash) ([]byte, error) { + it: newDiffAccountIterator(seek, accountList, func(hash common.Hash) ([]byte, error) { dl.lock.RLock() defer dl.lock.RUnlock() @@ -98,19 +104,26 @@ func newFastIterator(db *Database, root common.Hash, account common.Hash, seek c case *diffLayer: // The state set in diff layer is immutable and will never be stale, // so the read lock protection is unnecessary. + accountList := dl.states.accountList() fi.iterators = append(fi.iterators, &weightedIterator{ - it: newDiffAccountIterator(seek, dl.states.stateSet, dl.states.mustAccount), + it: newDiffAccountIterator(seek, accountList, dl.states.mustAccount), priority: depth, }) } } else { switch dl := current.(type) { case *diskLayer: + // The state set in the disk layer is mutable, hold the lock before obtaining + // the storage list to prevent concurrent map iteration and write. + dl.lock.RLock() + storageList := dl.buffer.states.storageList(account) + dl.lock.RUnlock() + fi.iterators = append(fi.iterators, &weightedIterator{ // The state set in the disk layer is mutable, and the entire state becomes stale // if a diff layer above is merged into it. Therefore, staleness must be checked, // and the storage slot should be retrieved with read lock protection. - it: newDiffStorageIterator(account, seek, dl.buffer.states, func(addrHash common.Hash, slotHash common.Hash) ([]byte, error) { + it: newDiffStorageIterator(account, seek, storageList, func(addrHash common.Hash, slotHash common.Hash) ([]byte, error) { dl.lock.RLock() defer dl.lock.RUnlock() @@ -126,10 +139,14 @@ func newFastIterator(db *Database, root common.Hash, account common.Hash, seek c priority: depth + 1, }) case *diffLayer: + // The state set in diff layer is immutable and will never be stale, + // so the read lock protection is unnecessary. + storageList := dl.states.storageList(account) + // The state set in diff layer is immutable and will never be stale, // so the read lock protection is unnecessary. fi.iterators = append(fi.iterators, &weightedIterator{ - it: newDiffStorageIterator(account, seek, dl.states.stateSet, dl.states.mustStorage), + it: newDiffStorageIterator(account, seek, storageList, dl.states.mustStorage), priority: depth, }) } diff --git a/triedb/pathdb/iterator_test.go b/triedb/pathdb/iterator_test.go index 3894118034..6517735d7e 100644 --- a/triedb/pathdb/iterator_test.go +++ b/triedb/pathdb/iterator_test.go @@ -132,18 +132,15 @@ func TestAccountIteratorBasics(t *testing.T) { } } states := newStates(accounts, storage, false) - it := newDiffAccountIterator(common.Hash{}, states, nil) + it := newDiffAccountIterator(common.Hash{}, states.accountList(), nil) verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator - // TODO reenable these tests once the persistent state iteration - // is implemented. - - //db := rawdb.NewMemoryDatabase() - //batch := db.NewBatch() - //states.write(db, batch, nil, nil) - //batch.Write() - //it = newDiskAccountIterator(db, common.Hash{}) - //verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator + db := rawdb.NewMemoryDatabase() + batch := db.NewBatch() + states.write(batch, nil, nil) + batch.Write() + it = newDiskAccountIterator(db, common.Hash{}) + verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator } // TestStorageIteratorBasics tests some simple single-layer(diff and disk) iteration for storage @@ -173,21 +170,18 @@ func TestStorageIteratorBasics(t *testing.T) { } states := newStates(accounts, storage, false) for account := range accounts { - it := newDiffStorageIterator(account, common.Hash{}, states, nil) + it := newDiffStorageIterator(account, common.Hash{}, states.storageList(account), nil) verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator } - // TODO reenable these tests once the persistent state iteration - // is implemented. - - //db := rawdb.NewMemoryDatabase() - //batch := db.NewBatch() - //states.write(db, batch, nil, nil) - //batch.Write() - //for account := range accounts { - // it := newDiskStorageIterator(db, account, common.Hash{}) - // verifyIterator(t, 100-nilStorage[account], it, verifyNothing) // Nil is allowed for single layer iterator - //} + db := rawdb.NewMemoryDatabase() + batch := db.NewBatch() + states.write(batch, nil, nil) + batch.Write() + for account := range accounts { + it := newDiskStorageIterator(db, account, common.Hash{}) + verifyIterator(t, 100-nilStorage[account], it, verifyNothing) // Nil is allowed for single layer iterator + } } type testIterator struct { @@ -263,7 +257,7 @@ func TestAccountIteratorTraversal(t *testing.T) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 0, trienode.NewMergedNodeSet(), @@ -279,7 +273,7 @@ func TestAccountIteratorTraversal(t *testing.T) { head := db.tree.get(common.HexToHash("0x04")) // singleLayer: 0xcc, 0xf0, 0xff - it := newDiffAccountIterator(common.Hash{}, head.(*diffLayer).states.stateSet, nil) + it := newDiffAccountIterator(common.Hash{}, head.(*diffLayer).states.stateSet.accountList(), nil) verifyIterator(t, 3, it, verifyNothing) // binaryIterator: 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xf0, 0xff @@ -290,19 +284,16 @@ func TestAccountIteratorTraversal(t *testing.T) { verifyIterator(t, 7, it, verifyAccount) it.Release() - // TODO reenable these tests once the persistent state iteration - // is implemented. - // Test after persist some bottom-most layers into the disk, // the functionalities still work. - //db.tree.cap(common.HexToHash("0x04"), 2) - - //head = db.tree.get(common.HexToHash("0x04")) - //verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) - // - //it, _ = db.AccountIterator(common.HexToHash("0x04"), common.Hash{}) - //verifyIterator(t, 7, it, verifyAccount) - //it.Release() + db.tree.cap(common.HexToHash("0x04"), 2) + + head = db.tree.get(common.HexToHash("0x04")) + verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(common.Hash{}), verifyAccount) + + it, _ = db.AccountIterator(common.HexToHash("0x04"), common.Hash{}) + verifyIterator(t, 7, it, verifyAccount) + it.Release() } func TestStorageIteratorTraversal(t *testing.T) { @@ -310,7 +301,7 @@ func TestStorageIteratorTraversal(t *testing.T) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 0, trienode.NewMergedNodeSet(), @@ -326,7 +317,7 @@ func TestStorageIteratorTraversal(t *testing.T) { head := db.tree.get(common.HexToHash("0x04")) // singleLayer: 0x1, 0x2, 0x3 - diffIter := newDiffStorageIterator(common.HexToHash("0xaa"), common.Hash{}, head.(*diffLayer).states.stateSet, nil) + diffIter := newDiffStorageIterator(common.HexToHash("0xaa"), common.Hash{}, head.(*diffLayer).states.stateSet.storageList(common.HexToHash("0xaa")), nil) verifyIterator(t, 3, diffIter, verifyNothing) // binaryIterator: 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 @@ -337,17 +328,14 @@ func TestStorageIteratorTraversal(t *testing.T) { verifyIterator(t, 6, it, verifyStorage) it.Release() - // TODO reenable these tests once the persistent state iteration - // is implemented. - // Test after persist some bottom-most layers into the disk, // the functionalities still work. - //db.tree.cap(common.HexToHash("0x04"), 2) - //verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage) - // - //it, _ = db.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) - //verifyIterator(t, 6, it, verifyStorage) - //it.Release() + db.tree.cap(common.HexToHash("0x04"), 2) + verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}), verifyStorage) + + it, _ = db.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) + verifyIterator(t, 6, it, verifyStorage) + it.Release() } // TestAccountIteratorTraversalValues tests some multi-layer iteration, where we @@ -357,7 +345,7 @@ func TestAccountIteratorTraversalValues(t *testing.T) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // Create a batch of account sets to seed subsequent layers with var ( @@ -434,26 +422,38 @@ func TestAccountIteratorTraversalValues(t *testing.T) { } it.Release() - // TODO reenable these tests once the persistent state iteration - // is implemented. - // Test after persist some bottom-most layers into the disk, // the functionalities still work. - //db.tree.cap(common.HexToHash("0x09"), 2) - // - //it, _ = db.AccountIterator(common.HexToHash("0x09"), common.Hash{}) - //for it.Next() { - // hash := it.Hash() - // account, err := head.Account(hash) - // if err != nil { - // t.Fatalf("failed to retrieve expected account: %v", err) - // } - // want, _ := rlp.EncodeToBytes(account) - // if have := it.Account(); !bytes.Equal(want, have) { - // t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) - // } - //} - //it.Release() + db.tree.cap(common.HexToHash("0x09"), 2) + + // binaryIterator + head = db.tree.get(common.HexToHash("0x09")) + it = head.(*diffLayer).newBinaryAccountIterator(common.Hash{}) + for it.Next() { + hash := it.Hash() + want, err := r.(*reader).AccountRLP(hash) + if err != nil { + t.Fatalf("failed to retrieve expected account: %v", err) + } + if have := it.Account(); !bytes.Equal(want, have) { + t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) + } + } + it.Release() + + // fastIterator + it, _ = db.AccountIterator(common.HexToHash("0x09"), common.Hash{}) + for it.Next() { + hash := it.Hash() + want, err := r.(*reader).AccountRLP(hash) + if err != nil { + t.Fatalf("failed to retrieve expected account: %v", err) + } + if have := it.Account(); !bytes.Equal(want, have) { + t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) + } + } + it.Release() } func TestStorageIteratorTraversalValues(t *testing.T) { @@ -461,7 +461,7 @@ func TestStorageIteratorTraversalValues(t *testing.T) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() wrapStorage := func(storage map[common.Hash][]byte) map[common.Hash]map[common.Hash][]byte { return map[common.Hash]map[common.Hash][]byte{ @@ -543,25 +543,38 @@ func TestStorageIteratorTraversalValues(t *testing.T) { } it.Release() - // TODO reenable these tests once the persistent state iteration - // is implemented. - // Test after persist some bottom-most layers into the disk, // the functionalities still work. - //db.tree.cap(common.HexToHash("0x09"), 2) - // - //it, _ = db.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) - //for it.Next() { - // hash := it.Hash() - // want, err := head.Storage(common.HexToHash("0xaa"), hash) - // if err != nil { - // t.Fatalf("failed to retrieve expected slot: %v", err) - // } - // if have := it.Slot(); !bytes.Equal(want, have) { - // t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) - // } - //} - //it.Release() + db.tree.cap(common.HexToHash("0x09"), 2) + + // binaryIterator + head = db.tree.get(common.HexToHash("0x09")) + it = head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}) + for it.Next() { + hash := it.Hash() + want, err := r.Storage(common.HexToHash("0xaa"), hash) + if err != nil { + t.Fatalf("failed to retrieve expected account: %v", err) + } + if have := it.Slot(); !bytes.Equal(want, have) { + t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) + } + } + it.Release() + + // fastIterator + it, _ = db.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) + for it.Next() { + hash := it.Hash() + want, err := r.Storage(common.HexToHash("0xaa"), hash) + if err != nil { + t.Fatalf("failed to retrieve expected storage slot: %v", err) + } + if have := it.Slot(); !bytes.Equal(want, have) { + t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) + } + } + it.Release() } // This testcase is notorious, all layers contain the exact same 200 accounts. @@ -581,7 +594,8 @@ func TestAccountIteratorLargeTraversal(t *testing.T) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() + for i := 1; i < 128; i++ { parent := types.EmptyRootHash if i == 1 { @@ -592,25 +606,22 @@ func TestAccountIteratorLargeTraversal(t *testing.T) { } // Iterate the entire stack and ensure everything is hit only once head := db.tree.get(common.HexToHash("0x80")) - verifyIterator(t, 200, newDiffAccountIterator(common.Hash{}, head.(*diffLayer).states.stateSet, nil), verifyNothing) + verifyIterator(t, 200, newDiffAccountIterator(common.Hash{}, head.(*diffLayer).states.stateSet.accountList(), nil), verifyNothing) verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(common.Hash{}), verifyAccount) it, _ := db.AccountIterator(common.HexToHash("0x80"), common.Hash{}) verifyIterator(t, 200, it, verifyAccount) it.Release() - // TODO reenable these tests once the persistent state iteration - // is implemented. - // Test after persist some bottom-most layers into the disk, // the functionalities still work. - //db.tree.cap(common.HexToHash("0x80"), 2) - // - //verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) - // - //it, _ = db.AccountIterator(common.HexToHash("0x80"), common.Hash{}) - //verifyIterator(t, 200, it, verifyAccount) - //it.Release() + db.tree.cap(common.HexToHash("0x80"), 2) + + verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(common.Hash{}), verifyAccount) + + it, _ = db.AccountIterator(common.HexToHash("0x80"), common.Hash{}) + verifyIterator(t, 200, it, verifyAccount) + it.Release() } // TestAccountIteratorFlattening tests what happens when we @@ -622,7 +633,7 @@ func TestAccountIteratorFlattening(t *testing.T) { WriteBufferSize: 10 * 1024, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // Create a stack of diffs on top db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -655,7 +666,7 @@ func TestAccountIteratorSeek(t *testing.T) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil, nil, nil, false)) @@ -727,7 +738,7 @@ func testStorageIteratorSeek(t *testing.T, newIterator func(db *Database, root, WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -799,7 +810,7 @@ func testAccountIteratorDeletions(t *testing.T, newIterator func(db *Database, r WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -839,7 +850,7 @@ func TestStorageIteratorDeletions(t *testing.T) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -907,7 +918,7 @@ func testStaleIterator(t *testing.T, newIter func(db *Database, hash common.Hash WriteBufferSize: 16 * 1024 * 1024, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() // [02 (disk), 03] db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -962,7 +973,7 @@ func BenchmarkAccountIteratorTraversal(b *testing.B) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() for i := 1; i <= 100; i++ { parent := types.EmptyRootHash @@ -1057,7 +1068,7 @@ func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) { WriteBufferSize: 0, } db := New(rawdb.NewMemoryDatabase(), config, false) - // db.WaitGeneration() + db.waitGeneration() db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(makeAccounts(2000), nil, nil, nil, false)) for i := 2; i <= 100; i++ { diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 79a7a22e0b..5dc6da92b8 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" ) @@ -90,6 +91,56 @@ func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) { return head, nil } +// journalGenerator is a disk layer entry containing the generator progress marker. +type journalGenerator struct { + // Indicator that whether the database was in progress of being wiped. + // It's deprecated but keep it here for backward compatibility. + Wiping bool + + Done bool // Whether the generator finished creating the snapshot + Marker []byte + Accounts uint64 + Slots uint64 + Storage uint64 +} + +// loadGenerator loads the state generation progress marker from the database. +func loadGenerator(db ethdb.KeyValueReader, hash nodeHasher) (*journalGenerator, common.Hash, error) { + trieRoot, err := hash(rawdb.ReadAccountTrieNode(db, nil)) + if err != nil { + return nil, common.Hash{}, err + } + // State generation progress marker is lost, rebuild it + blob := rawdb.ReadSnapshotGenerator(db) + if len(blob) == 0 { + log.Info("State snapshot generator is not found") + return nil, trieRoot, nil + } + // State generation progress marker is not compatible, rebuild it + var generator journalGenerator + if err := rlp.DecodeBytes(blob, &generator); err != nil { + log.Info("State snapshot generator is not compatible") + return nil, trieRoot, nil + } + // The state snapshot is inconsistent with the trie data and must + // be rebuilt. + // + // Note: The SnapshotRoot and SnapshotGenerator are always consistent + // with each other, both in the legacy state snapshot and the path database. + // Therefore, if the SnapshotRoot does not match the trie root, + // the entire generator is considered stale and must be discarded. + stateRoot := rawdb.ReadSnapshotRoot(db) + if trieRoot != stateRoot { + log.Info("State snapshot is not consistent", "trie", trieRoot, "state", stateRoot) + return nil, trieRoot, nil + } + // Slice null-ness is lost after rlp decoding, reset it back to empty + if !generator.Done && generator.Marker == nil { + generator.Marker = []byte{} + } + return &generator, trieRoot, nil +} + // loadLayers loads a pre-existing state layer backed by a key-value store. func (db *Database) loadLayers() layer { // Retrieve the root node of persistent state. @@ -109,7 +160,7 @@ func (db *Database) loadLayers() layer { log.Info("Failed to load journal, discard it", "err", err) } // Return single layer with persistent state. - return newDiskLayer(root, rawdb.ReadPersistentStateID(db.diskdb), db, nil, newBuffer(db.config.WriteBufferSize, nil, nil, 0)) + return newDiskLayer(root, rawdb.ReadPersistentStateID(db.diskdb), db, nil, nil, newBuffer(db.config.WriteBufferSize, nil, nil, 0)) } // loadDiskLayer reads the binary blob from the layer journal, reconstructing @@ -141,7 +192,7 @@ func (db *Database) loadDiskLayer(r *rlp.Stream) (layer, error) { if err := states.decode(r); err != nil { return nil, err } - return newDiskLayer(root, id, db, nil, newBuffer(db.config.WriteBufferSize, &nodes, &states, id-stored)), nil + return newDiskLayer(root, id, db, nil, nil, newBuffer(db.config.WriteBufferSize, &nodes, &states, id-stored)), nil } // loadDiffLayer reads the next sections of a layer journal, reconstructing a new @@ -250,6 +301,10 @@ func (db *Database) Journal(root common.Hash) error { } else { // disk layer only on noop runs (likely) or deep reorgs (unlikely) log.Info("Persisting dirty state to disk", "root", root, "layers", disk.buffer.layers) } + // Terminate the background state generation if it's active + if disk.generator != nil { + disk.generator.stop() + } start := time.Now() // Run the journaling diff --git a/triedb/pathdb/metrics.go b/triedb/pathdb/metrics.go index abe2dfe1f6..502c34fc62 100644 --- a/triedb/pathdb/metrics.go +++ b/triedb/pathdb/metrics.go @@ -24,16 +24,26 @@ var ( cleanNodeReadMeter = metrics.NewRegisteredMeter("pathdb/clean/node/read", nil) cleanNodeWriteMeter = metrics.NewRegisteredMeter("pathdb/clean/node/write", nil) + cleanStateHitMeter = metrics.NewRegisteredMeter("pathdb/clean/state/hit", nil) + cleanStateMissMeter = metrics.NewRegisteredMeter("pathdb/clean/state/miss", nil) + cleanStateReadMeter = metrics.NewRegisteredMeter("pathdb/clean/state/read", nil) + cleanStateWriteMeter = metrics.NewRegisteredMeter("pathdb/clean/state/write", nil) + dirtyNodeHitMeter = metrics.NewRegisteredMeter("pathdb/dirty/node/hit", nil) dirtyNodeMissMeter = metrics.NewRegisteredMeter("pathdb/dirty/node/miss", nil) dirtyNodeReadMeter = metrics.NewRegisteredMeter("pathdb/dirty/node/read", nil) dirtyNodeWriteMeter = metrics.NewRegisteredMeter("pathdb/dirty/node/write", nil) dirtyNodeHitDepthHist = metrics.NewRegisteredHistogram("pathdb/dirty/node/depth", nil, metrics.NewExpDecaySample(1028, 0.015)) - stateAccountInexMeter = metrics.NewRegisteredMeter("pathdb/state/account/inex/total", nil) - stateStorageInexMeter = metrics.NewRegisteredMeter("pathdb/state/storage/inex/total", nil) - stateAccountExistMeter = metrics.NewRegisteredMeter("pathdb/state/account/exist/total", nil) - stateStorageExistMeter = metrics.NewRegisteredMeter("pathdb/state/storage/exist/total", nil) + stateAccountInexMeter = metrics.NewRegisteredMeter("pathdb/state/account/inex/total", nil) + stateStorageInexMeter = metrics.NewRegisteredMeter("pathdb/state/storage/inex/total", nil) + stateAccountInexDiskMeter = metrics.NewRegisteredMeter("pathdb/state/account/inex/disk", nil) + stateStorageInexDiskMeter = metrics.NewRegisteredMeter("pathdb/state/storage/inex/disk", nil) + + stateAccountExistMeter = metrics.NewRegisteredMeter("pathdb/state/account/exist/total", nil) + stateStorageExistMeter = metrics.NewRegisteredMeter("pathdb/state/storage/exist/total", nil) + stateAccountExistDiskMeter = metrics.NewRegisteredMeter("pathdb/state/account/exist/disk", nil) + stateStorageExistDiskMeter = metrics.NewRegisteredMeter("pathdb/state/storage/exist/disk", nil) dirtyStateHitMeter = metrics.NewRegisteredMeter("pathdb/dirty/state/hit", nil) dirtyStateMissMeter = metrics.NewRegisteredMeter("pathdb/dirty/state/miss", nil) @@ -46,9 +56,11 @@ var ( nodeDiskFalseMeter = metrics.NewRegisteredMeter("pathdb/disk/false", nil) nodeDiffFalseMeter = metrics.NewRegisteredMeter("pathdb/diff/false", nil) - commitTimeTimer = metrics.NewRegisteredResettingTimer("pathdb/commit/time", nil) - commitNodesMeter = metrics.NewRegisteredMeter("pathdb/commit/nodes", nil) - commitBytesMeter = metrics.NewRegisteredMeter("pathdb/commit/bytes", nil) + commitTimeTimer = metrics.NewRegisteredResettingTimer("pathdb/commit/time", nil) + commitNodesMeter = metrics.NewRegisteredMeter("pathdb/commit/nodes", nil) + commitAccountsMeter = metrics.NewRegisteredMeter("pathdb/commit/accounts", nil) + commitStoragesMeter = metrics.NewRegisteredMeter("pathdb/commit/slots", nil) + commitBytesMeter = metrics.NewRegisteredMeter("pathdb/commit/bytes", nil) gcTrieNodeMeter = metrics.NewRegisteredMeter("pathdb/gc/node/count", nil) gcTrieNodeBytesMeter = metrics.NewRegisteredMeter("pathdb/gc/node/bytes", nil) @@ -61,3 +73,28 @@ var ( historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil) historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil) ) + +// Metrics in generation +var ( + generatedAccountMeter = metrics.NewRegisteredMeter("pathdb/generation/account/generated", nil) + recoveredAccountMeter = metrics.NewRegisteredMeter("pathdb/generation/account/recovered", nil) + wipedAccountMeter = metrics.NewRegisteredMeter("pathdb/generation/account/wiped", nil) + missallAccountMeter = metrics.NewRegisteredMeter("pathdb/generation/account/missall", nil) + generatedStorageMeter = metrics.NewRegisteredMeter("pathdb/generation/storage/generated", nil) + recoveredStorageMeter = metrics.NewRegisteredMeter("pathdb/generation/storage/recovered", nil) + wipedStorageMeter = metrics.NewRegisteredMeter("pathdb/generation/storage/wiped", nil) + missallStorageMeter = metrics.NewRegisteredMeter("pathdb/generation/storage/missall", nil) + danglingStorageMeter = metrics.NewRegisteredMeter("pathdb/generation/storage/dangling", nil) + successfulRangeProofMeter = metrics.NewRegisteredMeter("pathdb/generation/proof/success", nil) + failedRangeProofMeter = metrics.NewRegisteredMeter("pathdb/generation/proof/failure", nil) + + accountProveCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/account/prove", nil) + accountTrieReadCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/account/trieread", nil) + accountSnapReadCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/account/snapread", nil) + accountWriteCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/account/write", nil) + storageProveCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/storage/prove", nil) + storageTrieReadCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/storage/trieread", nil) + storageSnapReadCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/storage/snapread", nil) + storageWriteCounter = metrics.NewRegisteredCounter("pathdb/generation/duration/storage/write", nil) + storageCleanCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/clean", nil) +) diff --git a/triedb/pathdb/states.go b/triedb/pathdb/states.go index 0a83b2f2cc..2a88d74f5f 100644 --- a/triedb/pathdb/states.go +++ b/triedb/pathdb/states.go @@ -23,8 +23,10 @@ import ( "slices" "sync" + "github.com/VictoriaMetrics/fastcache" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" @@ -416,6 +418,11 @@ func (s *stateSet) decode(r *rlp.Stream) error { return nil } +// write flushes state mutations into the provided database batch as a whole. +func (s *stateSet) write(batch ethdb.Batch, genMarker []byte, clean *fastcache.Cache) (int, int) { + return writeStates(batch, genMarker, s.accountData, s.storageData, clean) +} + // reset clears all cached state data, including any optional sorted lists that // may have been generated. func (s *stateSet) reset() { @@ -427,8 +434,6 @@ func (s *stateSet) reset() { } // dbsize returns the approximate size for db write. -// -// nolint:unused func (s *stateSet) dbsize() int { m := len(s.accountData) * len(rawdb.SnapshotAccountPrefix) for _, slots := range s.storageData { From 7e7925460507db9988088223ecd069af507815d6 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Fri, 16 May 2025 17:10:47 +0200 Subject: [PATCH 030/365] eth/protocols/eth: implement eth/69 (#29158) This PR implements eth/69. This protocol version drops the bloom filter from receipts messages, reducing the amount of data needed for a sync by ~530GB (2.3B txs * 256 byte) uncompressed. Compressed this will be reduced to ~100GB The new version also changes the Status message and introduces the BlockRangeUpdate message to relay information about the available history range. --------- Co-authored-by: Felix Lange --- cmd/devp2p/internal/ethtest/conn.go | 28 +- cmd/devp2p/internal/ethtest/protocol.go | 2 +- cmd/devp2p/internal/ethtest/suite.go | 73 ++- cmd/utils/cmd.go | 3 +- core/blockchain.go | 13 +- core/blockchain_reader.go | 14 +- core/blockchain_test.go | 22 +- core/filtermaps/chain_view.go | 4 +- core/filtermaps/indexer_test.go | 2 +- core/rawdb/accessors_chain.go | 25 +- core/rawdb/accessors_chain_test.go | 12 +- core/txindexer_test.go | 8 +- core/types/bloom9.go | 21 +- core/types/receipt.go | 24 +- core/types/receipt_test.go | 290 +++++------ eth/downloader/downloader.go | 7 +- eth/downloader/downloader_test.go | 9 +- .../fetchers_concurrent_receipts.go | 2 +- eth/downloader/queue.go | 9 +- eth/downloader/queue_test.go | 6 +- eth/filters/filter_system_test.go | 7 +- eth/handler.go | 160 +++++- eth/handler_eth_test.go | 13 +- eth/peer.go | 18 +- eth/protocols/eth/handler.go | 27 +- eth/protocols/eth/handler_test.go | 17 +- eth/protocols/eth/handlers.go | 140 ++++-- eth/protocols/eth/handshake.go | 174 +++++-- eth/protocols/eth/handshake_test.go | 10 +- eth/protocols/eth/peer.go | 16 + eth/protocols/eth/protocol.go | 65 ++- eth/protocols/eth/protocol_test.go | 35 +- eth/protocols/eth/receipt.go | 462 ++++++++++++++++++ eth/protocols/eth/receipt_test.go | 158 ++++++ eth/protocols/eth/tracker.go | 26 - 35 files changed, 1513 insertions(+), 389 deletions(-) create mode 100644 eth/protocols/eth/receipt.go create mode 100644 eth/protocols/eth/receipt_test.go delete mode 100644 eth/protocols/eth/tracker.go diff --git a/cmd/devp2p/internal/ethtest/conn.go b/cmd/devp2p/internal/ethtest/conn.go index a7bc70cbf5..6d8e0f1f7e 100644 --- a/cmd/devp2p/internal/ethtest/conn.go +++ b/cmd/devp2p/internal/ethtest/conn.go @@ -66,10 +66,9 @@ func (s *Suite) dialAs(key *ecdsa.PrivateKey) (*Conn, error) { return nil, err } conn.caps = []p2p.Cap{ - {Name: "eth", Version: 67}, - {Name: "eth", Version: 68}, + {Name: "eth", Version: 69}, } - conn.ourHighestProtoVersion = 68 + conn.ourHighestProtoVersion = 69 return &conn, nil } @@ -156,7 +155,7 @@ func (c *Conn) ReadEth() (any, error) { var msg any switch int(code) { case eth.StatusMsg: - msg = new(eth.StatusPacket) + msg = new(eth.StatusPacket69) case eth.GetBlockHeadersMsg: msg = new(eth.GetBlockHeadersPacket) case eth.BlockHeadersMsg: @@ -231,7 +230,7 @@ func (c *Conn) ReadSnap() (any, error) { // peer performs both the protocol handshake and the status message // exchange with the node in order to peer with it. -func (c *Conn) peer(chain *Chain, status *eth.StatusPacket) error { +func (c *Conn) peer(chain *Chain, status *eth.StatusPacket69) error { if err := c.handshake(); err != nil { return fmt.Errorf("handshake failed: %v", err) } @@ -304,7 +303,7 @@ func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) { } // statusExchange performs a `Status` message exchange with the given node. -func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket) error { +func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket69) error { loop: for { code, data, err := c.Read() @@ -313,12 +312,16 @@ loop: } switch code { case eth.StatusMsg + protoOffset(ethProto): - msg := new(eth.StatusPacket) + msg := new(eth.StatusPacket69) if err := rlp.DecodeBytes(data, &msg); err != nil { return fmt.Errorf("error decoding status packet: %w", err) } - if have, want := msg.Head, chain.blocks[chain.Len()-1].Hash(); have != want { - return fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x", + if have, want := msg.LatestBlock, chain.blocks[chain.Len()-1].NumberU64(); have != want { + return fmt.Errorf("wrong head block in status, want: %d, have %d", + want, have) + } + if have, want := msg.LatestBlockHash, chain.blocks[chain.Len()-1].Hash(); have != want { + return fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x", want, chain.blocks[chain.Len()-1].NumberU64(), have) } if have, want := msg.ForkID, chain.ForkID(); !reflect.DeepEqual(have, want) { @@ -348,13 +351,14 @@ loop: } if status == nil { // default status message - status = ð.StatusPacket{ + status = ð.StatusPacket69{ ProtocolVersion: uint32(c.negotiatedProtoVersion), NetworkID: chain.config.ChainID.Uint64(), - TD: chain.TD(), - Head: chain.blocks[chain.Len()-1].Hash(), Genesis: chain.blocks[0].Hash(), ForkID: chain.ForkID(), + EarliestBlock: 0, + LatestBlock: chain.blocks[chain.Len()-1].NumberU64(), + LatestBlockHash: chain.blocks[chain.Len()-1].Hash(), } } if err := c.Write(ethProto, eth.StatusMsg, status); err != nil { diff --git a/cmd/devp2p/internal/ethtest/protocol.go b/cmd/devp2p/internal/ethtest/protocol.go index 5c2f7d9e48..a21d1ca7a1 100644 --- a/cmd/devp2p/internal/ethtest/protocol.go +++ b/cmd/devp2p/internal/ethtest/protocol.go @@ -32,7 +32,7 @@ const ( // Unexported devp2p protocol lengths from p2p package. const ( baseProtoLen = 16 - ethProtoLen = 17 + ethProtoLen = 18 snapProtoLen = 8 ) diff --git a/cmd/devp2p/internal/ethtest/suite.go b/cmd/devp2p/internal/ethtest/suite.go index a16d308dfd..b90ecf3ca3 100644 --- a/cmd/devp2p/internal/ethtest/suite.go +++ b/cmd/devp2p/internal/ethtest/suite.go @@ -74,8 +74,9 @@ func (s *Suite) EthTests() []utesting.Test { {Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests}, {Name: "SameRequestID", Fn: s.TestSameRequestID}, {Name: "ZeroRequestID", Fn: s.TestZeroRequestID}, - // get block bodies + // get history {Name: "GetBlockBodies", Fn: s.TestGetBlockBodies}, + {Name: "GetReceipts", Fn: s.TestGetReceipts}, // // malicious handshakes + status {Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake}, // test transactions @@ -418,6 +419,51 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) { } } +func (s *Suite) TestGetReceipts(t *utesting.T) { + t.Log(`This test sends GetReceipts requests to the node for known blocks in the test chain.`) + + conn, err := s.dial() + if err != nil { + t.Fatalf("dial failed: %v", err) + } + defer conn.Close() + if err := conn.peer(s.chain, nil); err != nil { + t.Fatalf("peering failed: %v", err) + } + + // Find some blocks containing receipts. + var hashes = make([]common.Hash, 0, 3) + for i := range s.chain.Len() { + block := s.chain.GetBlock(i) + if len(block.Transactions()) > 0 { + hashes = append(hashes, block.Hash()) + } + if len(hashes) == cap(hashes) { + break + } + } + + // Create block bodies request. + req := ð.GetReceiptsPacket{ + RequestId: 66, + GetReceiptsRequest: (eth.GetReceiptsRequest)(hashes), + } + if err := conn.Write(ethProto, eth.GetReceiptsMsg, req); err != nil { + t.Fatalf("could not write to connection: %v", err) + } + // Wait for response. + resp := new(eth.ReceiptsPacket[*eth.ReceiptList69]) + if err := conn.ReadMsg(ethProto, eth.ReceiptsMsg, &resp); err != nil { + t.Fatalf("error reading block bodies msg: %v", err) + } + if got, want := resp.RequestId, req.RequestId; got != want { + t.Fatalf("unexpected request id in respond", got, want) + } + if len(resp.List) != len(req.GetReceiptsRequest) { + t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetReceiptsRequest), len(resp.List)) + } +} + // randBuf makes a random buffer size kilobytes large. func randBuf(size int) []byte { buf := make([]byte, size*1024) @@ -500,6 +546,31 @@ func (s *Suite) TestMaliciousHandshake(t *utesting.T) { } } +func (s *Suite) TestInvalidBlockRangeUpdate(t *utesting.T) { + t.Log(`This test sends an invalid BlockRangeUpdate message to the node and expects to be disconnected.`) + + conn, err := s.dial() + if err != nil { + t.Fatalf("dial failed: %v", err) + } + defer conn.Close() + if err := conn.peer(s.chain, nil); err != nil { + t.Fatalf("peering failed: %v", err) + } + + conn.Write(ethProto, eth.BlockRangeUpdateMsg, ð.BlockRangeUpdatePacket{ + EarliestBlock: 10, + LatestBlock: 8, + LatestBlockHash: s.chain.GetBlock(8).Hash(), + }) + + if code, _, err := conn.Read(); err != nil { + t.Fatalf("expected disconnect, got err: %v", err) + } else if code != discMsg { + t.Fatalf("expected disconnect message, got msg code %d", code) + } +} + func (s *Suite) TestTransaction(t *utesting.T) { t.Log(`This test sends a valid transaction to the node and checks if the transaction gets propagated.`) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index d34e15ebc0..b332a060de 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -309,7 +309,8 @@ func ImportHistory(chain *core.BlockChain, dir string, network string) error { if err != nil { return fmt.Errorf("error reading receipts %d: %w", it.Number(), err) } - if _, err := chain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{receipts}, 2^64-1); err != nil { + encReceipts := types.EncodeBlockReceiptLists([]types.Receipts{receipts}) + if _, err := chain.InsertReceiptChain([]*types.Block{block}, encReceipts, 2^64-1); err != nil { return fmt.Errorf("error inserting body %d: %w", it.Number(), err) } imported += 1 diff --git a/core/blockchain.go b/core/blockchain.go index f93cddfe44..64345bc1a3 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1309,12 +1309,11 @@ const ( // // The optional ancientLimit can also be specified and chain segment before that // will be directly stored in the ancient, getting rid of the chain migration. -func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts, ancientLimit uint64) (int, error) { +func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []rlp.RawValue, ancientLimit uint64) (int, error) { // Verify the supplied headers before insertion without lock var headers []*types.Header for _, block := range blockChain { headers = append(headers, block.Header()) - // Here we also validate that blob transactions in the block do not // contain a sidecar. While the sidecar does not affect the block hash // or tx hash, sending blobs within a block is not allowed. @@ -1357,11 +1356,11 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ // // this function only accepts canonical chain data. All side chain will be reverted // eventually. - writeAncient := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { + writeAncient := func(blockChain types.Blocks, receiptChain []rlp.RawValue) (int, error) { // Ensure genesis is in the ancient store if blockChain[0].NumberU64() == 1 { if frozen, _ := bc.db.Ancients(); frozen == 0 { - writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}) + writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList}) if err != nil { log.Error("Error writing genesis to ancients", "err", err) return 0, err @@ -1404,7 +1403,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ // existing local chain segments (reorg around the chain tip). The reorganized part // will be included in the provided chain segment, and stale canonical markers will be // silently rewritten. Therefore, no explicit reorg logic is needed. - writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { + writeLive := func(blockChain types.Blocks, receiptChain []rlp.RawValue) (int, error) { var ( skipPresenceCheck = false batch = bc.db.NewBatch() @@ -1429,7 +1428,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ // Write all the data out into the database rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64()) rawdb.WriteBlock(batch, block) - rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i]) + rawdb.WriteRawReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i]) // Write everything belongs to the blocks into the database. So that // we can ensure all components of body is completed(body, receipts) @@ -2650,7 +2649,7 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e first = headers[0].Number.Uint64() ) if first == 1 && frozen == 0 { - _, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}) + _, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList}) if err != nil { log.Error("Error writing genesis to ancients", "err", err) return 0, err diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index fefeb37542..c54948122d 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -234,12 +234,22 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { return receipts } -func (bc *BlockChain) GetRawReceiptsByHash(hash common.Hash) types.Receipts { +// GetRawReceipts retrieves the receipts for all transactions in a given block +// without deriving the internal fields and the Bloom. +func (bc *BlockChain) GetRawReceipts(hash common.Hash, number uint64) types.Receipts { + if receipts, ok := bc.receiptsCache.Get(hash); ok { + return receipts + } + return rawdb.ReadRawReceipts(bc.db, hash, number) +} + +// GetReceiptsRLP retrieves the receipts of a block. +func (bc *BlockChain) GetReceiptsRLP(hash common.Hash) rlp.RawValue { number := rawdb.ReadHeaderNumber(bc.db, hash) if number == nil { return nil } - return rawdb.ReadRawReceipts(bc.db, hash, *number) + return rawdb.ReadReceiptsRLP(bc.db, hash, *number) } // GetUnclesInChain retrieves all the uncles from a given block backwards until diff --git a/core/blockchain_test.go b/core/blockchain_test.go index b981c33f21..434b494490 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -734,7 +734,7 @@ func testFastVsFullChains(t *testing.T, scheme string) { fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) defer fast.Stop() - if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { + if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } // Freezer style fast import the chain. @@ -747,7 +747,7 @@ func testFastVsFullChains(t *testing.T, scheme string) { ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) defer ancient.Stop() - if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil { + if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(len(blocks)/2)); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } @@ -871,7 +871,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) defer fast.Stop() - if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { + if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } assert(t, "fast", fast, height, height, 0) @@ -884,7 +884,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) defer ancient.Stop() - if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { + if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } assert(t, "ancient", ancient, height, height, 0) @@ -1696,7 +1696,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) { defer ancientDb.Close() ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) - if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { + if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } rawdb.WriteLastPivotNumber(ancientDb, blocks[len(blocks)-1].NumberU64()) // Force fast sync behavior @@ -1991,7 +1991,7 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) { } } else if typ == "receipts" { inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - _, err = chain.InsertReceiptChain(blocks, receipts, 0) + _, err = chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0) return err } asserter = func(t *testing.T, block *types.Block) { @@ -2157,7 +2157,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i } } else if typ == "receipts" { inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - _, err = chain.InsertReceiptChain(blocks, receipts, 0) + _, err = chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0) return err } asserter = func(t *testing.T, block *types.Block) { @@ -4205,10 +4205,10 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) { chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) defer chain.Stop() - if n, err := chain.InsertReceiptChain(blocks, receipts, ancientLimit); err != nil { + if n, err := chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), ancientLimit); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } - if n, err := chain.InsertReceiptChain(chainA, receiptsA, ancientLimit); err != nil { + if n, err := chain.InsertReceiptChain(chainA, types.EncodeBlockReceiptLists(receiptsA), ancientLimit); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } // If the common ancestor is below the ancient limit, rewind the chain head. @@ -4218,7 +4218,7 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) { rawdb.WriteLastPivotNumber(db, ancestor) chain.SetHead(ancestor) } - if n, err := chain.InsertReceiptChain(chainB, receiptsB, ancientLimit); err != nil { + if n, err := chain.InsertReceiptChain(chainB, types.EncodeBlockReceiptLists(receiptsB), ancientLimit); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } head := chain.CurrentSnapBlock() @@ -4336,7 +4336,7 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64, if n, err := chain.InsertHeadersBeforeCutoff(headersBefore); err != nil { t.Fatalf("failed to insert headers before cutoff %d: %v", n, err) } - if n, err := chain.InsertReceiptChain(blocksAfter, receiptsAfter, ancientLimit); err != nil { + if n, err := chain.InsertReceiptChain(blocksAfter, types.EncodeBlockReceiptLists(receiptsAfter), ancientLimit); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } headSnap := chain.CurrentSnapBlock() diff --git a/core/filtermaps/chain_view.go b/core/filtermaps/chain_view.go index 874ff19e31..433ca07cd0 100644 --- a/core/filtermaps/chain_view.go +++ b/core/filtermaps/chain_view.go @@ -29,7 +29,7 @@ type blockchain interface { GetHeader(hash common.Hash, number uint64) *types.Header GetCanonicalHash(number uint64) common.Hash GetReceiptsByHash(hash common.Hash) types.Receipts - GetRawReceiptsByHash(hash common.Hash) types.Receipts + GetRawReceipts(hash common.Hash, number uint64) types.Receipts } // ChainView represents an immutable view of a chain with a block id and a set @@ -117,7 +117,7 @@ func (cv *ChainView) RawReceipts(number uint64) types.Receipts { log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber) return nil } - return cv.chain.GetRawReceiptsByHash(blockHash) + return cv.chain.GetRawReceipts(blockHash, number) } // SharedRange returns the block range shared by two chain views. diff --git a/core/filtermaps/indexer_test.go b/core/filtermaps/indexer_test.go index 2782b2cbe6..5ed397a90e 100644 --- a/core/filtermaps/indexer_test.go +++ b/core/filtermaps/indexer_test.go @@ -515,7 +515,7 @@ func (tc *testChain) GetReceiptsByHash(hash common.Hash) types.Receipts { return tc.receipts[hash] } -func (tc *testChain) GetRawReceiptsByHash(hash common.Hash) types.Receipts { +func (tc *testChain) GetRawReceipts(hash common.Hash, number uint64) types.Receipts { tc.lock.RLock() defer tc.lock.RUnlock() diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 2f62d86e4b..2386246caf 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -545,8 +545,8 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa } // ReadRawReceipts retrieves all the transaction receipts belonging to a block. -// The receipt metadata fields are not guaranteed to be populated, so they -// should not be used. Use ReadReceipts instead if the metadata is needed. +// The receipt metadata fields and the Bloom are not guaranteed to be populated, +// so they should not be used. Use ReadReceipts instead if the metadata is needed. func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { // Retrieve the flattened receipt slice data := ReadReceiptsRLP(db, hash, number) @@ -621,6 +621,14 @@ func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rec } } +// WriteRawReceipts stores all the transaction receipts belonging to a block. +func WriteRawReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts rlp.RawValue) { + // Store the flattened receipt slice + if err := db.Put(blockReceiptsKey(number, hash), receipts); err != nil { + log.Crit("Failed to store block receipts", "err", err) + } +} + // DeleteReceipts removes all receipt data associated with a block hash. func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { @@ -701,18 +709,11 @@ func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { } // WriteAncientBlocks writes entire block data into ancient store and returns the total written size. -func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []types.Receipts) (int64, error) { - var stReceipts []*types.ReceiptForStorage - +func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []rlp.RawValue) (int64, error) { return db.ModifyAncients(func(op ethdb.AncientWriteOp) error { for i, block := range blocks { - // Convert receipts to storage format and sum up total difficulty. - stReceipts = stReceipts[:0] - for _, receipt := range receipts[i] { - stReceipts = append(stReceipts, (*types.ReceiptForStorage)(receipt)) - } header := block.Header() - if err := writeAncientBlock(op, block, header, stReceipts); err != nil { + if err := writeAncientBlock(op, block, header, receipts[i]); err != nil { return err } } @@ -720,7 +721,7 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts }) } -func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage) error { +func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts rlp.RawValue) error { num := block.NumberU64() if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil { return fmt.Errorf("can't add block %d hash: %v", num, err) diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 247e277582..d98fc9a1eb 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -377,7 +377,11 @@ func TestBlockReceiptStorage(t *testing.T) { t.Fatalf("receipts returned when body was deleted: %v", rs) } // Ensure that receipts without metadata can be returned without the block body too - if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil { + raw := ReadRawReceipts(db, hash, 0) + for _, r := range raw { + r.Bloom = types.CreateBloom(r) + } + if err := checkReceiptsRLP(raw, receipts); err != nil { t.Fatal(err) } // Sanity check that body alone without the receipt is a full purge @@ -439,7 +443,7 @@ func TestAncientStorage(t *testing.T) { } // Write and verify the header in the database - WriteAncientBlocks(db, []*types.Block{block}, []types.Receipts{nil}) + WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil})) if blob := ReadHeaderRLP(db, hash, number); len(blob) == 0 { t.Fatalf("no header returned") @@ -609,7 +613,7 @@ func BenchmarkWriteAncientBlocks(b *testing.B) { blocks := allBlocks[i : i+length] receipts := batchReceipts[:length] - writeSize, err := WriteAncientBlocks(db, blocks, receipts) + writeSize, err := WriteAncientBlocks(db, blocks, types.EncodeBlockReceiptLists(receipts)) if err != nil { b.Fatal(err) } @@ -909,7 +913,7 @@ func TestHeadersRLPStorage(t *testing.T) { } receipts := make([]types.Receipts, 100) // Write first half to ancients - WriteAncientBlocks(db, chain[:50], receipts[:50]) + WriteAncientBlocks(db, chain[:50], types.EncodeBlockReceiptLists(receipts[:50])) // Write second half to db for i := 50; i < 100; i++ { WriteCanonicalHash(db, chain[i].Hash(), chain[i].NumberU64()) diff --git a/core/txindexer_test.go b/core/txindexer_test.go index 6543ff429d..615a34de41 100644 --- a/core/txindexer_test.go +++ b/core/txindexer_test.go @@ -117,7 +117,7 @@ func TestTxIndexer(t *testing.T) { } for _, c := range cases { db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) - rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...)) + rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...))) // Index the initial blocks from ancient store indexer := &txIndexer{ @@ -236,7 +236,8 @@ func TestTxIndexerRepair(t *testing.T) { } for _, c := range cases { db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) - rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...)) + encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...)) + rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts) // Index the initial blocks from ancient store indexer := &txIndexer{ @@ -426,7 +427,8 @@ func TestTxIndexerReport(t *testing.T) { } for _, c := range cases { db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) - rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...)) + encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...)) + rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts) // Index the initial blocks from ancient store indexer := &txIndexer{ diff --git a/core/types/bloom9.go b/core/types/bloom9.go index 962ba46d47..5a6e49c220 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -59,11 +59,12 @@ func (b *Bloom) SetBytes(d []byte) { // Add adds d to the filter. Future calls of Test(d) will return true. func (b *Bloom) Add(d []byte) { - b.add(d, make([]byte, 6)) + var buf [6]byte + b.AddWithBuffer(d, &buf) } // add is internal version of Add, which takes a scratch buffer for reuse (needs to be at least 6 bytes) -func (b *Bloom) add(d []byte, buf []byte) { +func (b *Bloom) AddWithBuffer(d []byte, buf *[6]byte) { i1, v1, i2, v2, i3, v3 := bloomValues(d, buf) b[i1] |= v1 b[i2] |= v2 @@ -84,7 +85,8 @@ func (b Bloom) Bytes() []byte { // Test checks if the given topic is present in the bloom filter func (b Bloom) Test(topic []byte) bool { - i1, v1, i2, v2, i3, v3 := bloomValues(topic, make([]byte, 6)) + var buf [6]byte + i1, v1, i2, v2, i3, v3 := bloomValues(topic, &buf) return v1 == v1&b[i1] && v2 == v2&b[i2] && v3 == v3&b[i3] @@ -104,12 +106,12 @@ func (b *Bloom) UnmarshalText(input []byte) error { func CreateBloom(receipt *Receipt) Bloom { var ( bin Bloom - buf = make([]byte, 6) + buf [6]byte ) for _, log := range receipt.Logs { - bin.add(log.Address.Bytes(), buf) + bin.AddWithBuffer(log.Address.Bytes(), &buf) for _, b := range log.Topics { - bin.add(b[:], buf) + bin.AddWithBuffer(b[:], &buf) } } return bin @@ -139,21 +141,20 @@ func Bloom9(data []byte) []byte { } // bloomValues returns the bytes (index-value pairs) to set for the given data -func bloomValues(data []byte, hashbuf []byte) (uint, byte, uint, byte, uint, byte) { +func bloomValues(data []byte, hashbuf *[6]byte) (uint, byte, uint, byte, uint, byte) { sha := hasherPool.Get().(crypto.KeccakState) sha.Reset() sha.Write(data) - sha.Read(hashbuf) + sha.Read(hashbuf[:]) hasherPool.Put(sha) // The actual bits to flip v1 := byte(1 << (hashbuf[1] & 0x7)) v2 := byte(1 << (hashbuf[3] & 0x7)) v3 := byte(1 << (hashbuf[5] & 0x7)) // The indices for the bytes to OR in - i1 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf)&0x7ff)>>3) - 1 + i1 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[0:])&0x7ff)>>3) - 1 i2 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[2:])&0x7ff)>>3) - 1 i3 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[4:])&0x7ff)>>3) - 1 - return i1, v1, i2, v2, i3, v3 } diff --git a/core/types/receipt.go b/core/types/receipt.go index e52a0c6477..ec99fbf888 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) @@ -258,7 +259,7 @@ func (r *Receipt) Size() common.StorageSize { } // ReceiptForStorage is a wrapper around a Receipt with RLP serialization -// that omits the Bloom field and deserialization that re-computes it. +// that omits the Bloom field. The Bloom field is recomputed by DeriveFields. type ReceiptForStorage Receipt // EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt @@ -291,7 +292,6 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { } r.CumulativeGasUsed = stored.CumulativeGasUsed r.Logs = stored.Logs - r.Bloom = CreateBloom((*Receipt)(r)) return nil } @@ -372,6 +372,26 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu rs[i].Logs[j].Index = logIndex logIndex++ } + // also derive the Bloom if not derived yet + rs[i].Bloom = CreateBloom(rs[i]) } return nil } + +// EncodeBlockReceiptLists encodes a list of block receipt lists into RLP. +func EncodeBlockReceiptLists(receipts []Receipts) []rlp.RawValue { + var storageReceipts []*ReceiptForStorage + result := make([]rlp.RawValue, len(receipts)) + for i, receipt := range receipts { + storageReceipts = storageReceipts[:0] + for _, r := range receipt { + storageReceipts = append(storageReceipts, (*ReceiptForStorage)(r)) + } + bytes, err := rlp.EncodeToBytes(storageReceipts) + if err != nil { + log.Crit("Failed to encode block receipts", "err", err) + } + result[i] = bytes + } + return result +} diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index 78b43c7e49..06cd0ff14c 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -22,6 +22,7 @@ import ( "math" "math/big" "reflect" + "sync" "testing" "github.com/ethereum/go-ethereum/common" @@ -154,147 +155,160 @@ var ( blockNumber = big.NewInt(1) blockTime = uint64(2) blockHash = common.BytesToHash([]byte{0x03, 0x14}) +) - // Create the corresponding receipts - receipts = Receipts{ - &Receipt{ - Status: ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*Log{ - { - Address: common.BytesToAddress([]byte{0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[0].Hash(), - TxIndex: 0, - BlockHash: blockHash, - Index: 0, - }, - { - Address: common.BytesToAddress([]byte{0x01, 0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[0].Hash(), - TxIndex: 0, - BlockHash: blockHash, - Index: 1, +var receiptsOnce sync.Once +var testReceipts Receipts + +func getTestReceipts() Receipts { + // Compute the blooms only once + receiptsOnce.Do(func() { + // Create the corresponding receipts + r := Receipts{ + &Receipt{ + Status: ReceiptStatusFailed, + CumulativeGasUsed: 1, + Logs: []*Log{ + { + Address: common.BytesToAddress([]byte{0x11}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + Index: 0, + }, + { + Address: common.BytesToAddress([]byte{0x01, 0x11}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + Index: 1, + }, }, + // derived fields: + TxHash: txs[0].Hash(), + ContractAddress: common.HexToAddress("0x5a443704dd4b594b382c22a083e2bd3090a6fef3"), + GasUsed: 1, + EffectiveGasPrice: big.NewInt(11), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 0, }, - // derived fields: - TxHash: txs[0].Hash(), - ContractAddress: common.HexToAddress("0x5a443704dd4b594b382c22a083e2bd3090a6fef3"), - GasUsed: 1, - EffectiveGasPrice: big.NewInt(11), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 0, - }, - &Receipt{ - PostState: common.Hash{2}.Bytes(), - CumulativeGasUsed: 3, - Logs: []*Log{ - { - Address: common.BytesToAddress([]byte{0x22}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[1].Hash(), - TxIndex: 1, - BlockHash: blockHash, - Index: 2, - }, - { - Address: common.BytesToAddress([]byte{0x02, 0x22}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[1].Hash(), - TxIndex: 1, - BlockHash: blockHash, - Index: 3, + &Receipt{ + PostState: common.Hash{2}.Bytes(), + CumulativeGasUsed: 3, + Logs: []*Log{ + { + Address: common.BytesToAddress([]byte{0x22}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + Index: 2, + }, + { + Address: common.BytesToAddress([]byte{0x02, 0x22}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + Index: 3, + }, }, + // derived fields: + TxHash: txs[1].Hash(), + GasUsed: 2, + EffectiveGasPrice: big.NewInt(22), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 1, }, - // derived fields: - TxHash: txs[1].Hash(), - GasUsed: 2, - EffectiveGasPrice: big.NewInt(22), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 1, - }, - &Receipt{ - Type: AccessListTxType, - PostState: common.Hash{3}.Bytes(), - CumulativeGasUsed: 6, - Logs: []*Log{}, - // derived fields: - TxHash: txs[2].Hash(), - GasUsed: 3, - EffectiveGasPrice: big.NewInt(33), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 2, - }, - &Receipt{ - Type: DynamicFeeTxType, - PostState: common.Hash{4}.Bytes(), - CumulativeGasUsed: 10, - Logs: []*Log{}, - // derived fields: - TxHash: txs[3].Hash(), - GasUsed: 4, - EffectiveGasPrice: big.NewInt(1044), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 3, - }, - &Receipt{ - Type: DynamicFeeTxType, - PostState: common.Hash{5}.Bytes(), - CumulativeGasUsed: 15, - Logs: []*Log{}, - // derived fields: - TxHash: txs[4].Hash(), - GasUsed: 5, - EffectiveGasPrice: big.NewInt(1055), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 4, - }, - &Receipt{ - Type: BlobTxType, - PostState: common.Hash{6}.Bytes(), - CumulativeGasUsed: 21, - Logs: []*Log{}, - // derived fields: - TxHash: txs[5].Hash(), - GasUsed: 6, - EffectiveGasPrice: big.NewInt(1066), - BlobGasUsed: params.BlobTxBlobGasPerBlob, - BlobGasPrice: big.NewInt(920), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 5, - }, - &Receipt{ - Type: BlobTxType, - PostState: common.Hash{7}.Bytes(), - CumulativeGasUsed: 28, - Logs: []*Log{}, - // derived fields: - TxHash: txs[6].Hash(), - GasUsed: 7, - EffectiveGasPrice: big.NewInt(1077), - BlobGasUsed: 3 * params.BlobTxBlobGasPerBlob, - BlobGasPrice: big.NewInt(920), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 6, - }, - } -) + &Receipt{ + Type: AccessListTxType, + PostState: common.Hash{3}.Bytes(), + CumulativeGasUsed: 6, + Logs: []*Log{}, + // derived fields: + TxHash: txs[2].Hash(), + GasUsed: 3, + EffectiveGasPrice: big.NewInt(33), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 2, + }, + &Receipt{ + Type: DynamicFeeTxType, + PostState: common.Hash{4}.Bytes(), + CumulativeGasUsed: 10, + Logs: []*Log{}, + // derived fields: + TxHash: txs[3].Hash(), + GasUsed: 4, + EffectiveGasPrice: big.NewInt(1044), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 3, + }, + &Receipt{ + Type: DynamicFeeTxType, + PostState: common.Hash{5}.Bytes(), + CumulativeGasUsed: 15, + Logs: []*Log{}, + // derived fields: + TxHash: txs[4].Hash(), + GasUsed: 5, + EffectiveGasPrice: big.NewInt(1055), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 4, + }, + &Receipt{ + Type: BlobTxType, + PostState: common.Hash{6}.Bytes(), + CumulativeGasUsed: 21, + Logs: []*Log{}, + // derived fields: + TxHash: txs[5].Hash(), + GasUsed: 6, + EffectiveGasPrice: big.NewInt(1066), + BlobGasUsed: params.BlobTxBlobGasPerBlob, + BlobGasPrice: big.NewInt(920), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 5, + }, + &Receipt{ + Type: BlobTxType, + PostState: common.Hash{7}.Bytes(), + CumulativeGasUsed: 28, + Logs: []*Log{}, + // derived fields: + TxHash: txs[6].Hash(), + GasUsed: 7, + EffectiveGasPrice: big.NewInt(1077), + BlobGasUsed: 3 * params.BlobTxBlobGasPerBlob, + BlobGasPrice: big.NewInt(920), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 6, + }, + } + for _, receipt := range r { + receipt.Bloom = CreateBloom(receipt) + } + testReceipts = r + }) + return testReceipts +} func TestDecodeEmptyTypedReceipt(t *testing.T) { input := []byte{0x80} @@ -310,6 +324,7 @@ func TestDeriveFields(t *testing.T) { // Re-derive receipts. basefee := big.NewInt(1000) blobGasPrice := big.NewInt(920) + receipts := getTestReceipts() derivedReceipts := clearComputedFieldsOnReceipts(receipts) err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), blockTime, basefee, blobGasPrice, txs) if err != nil { @@ -335,6 +350,7 @@ func TestDeriveFields(t *testing.T) { // Test that we can marshal/unmarshal receipts to/from json without errors. // This also confirms that our test receipts contain all the required fields. func TestReceiptJSON(t *testing.T) { + receipts := getTestReceipts() for i := range receipts { b, err := receipts[i].MarshalJSON() if err != nil { @@ -351,6 +367,7 @@ func TestReceiptJSON(t *testing.T) { // Test we can still parse receipt without EffectiveGasPrice for backwards compatibility, even // though it is required per the spec. func TestEffectiveGasPriceNotRequired(t *testing.T) { + receipts := getTestReceipts() r := *receipts[0] r.EffectiveGasPrice = nil b, err := r.MarshalJSON() @@ -511,6 +528,7 @@ func clearComputedFieldsOnReceipt(receipt *Receipt) *Receipt { cpy.EffectiveGasPrice = big.NewInt(0) cpy.BlobGasUsed = 0 cpy.BlobGasPrice = nil + cpy.Bloom = CreateBloom(&cpy) return &cpy } diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 4d13ae304c..762fb9283e 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -36,6 +36,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/triedb" ) @@ -202,7 +203,7 @@ type BlockChain interface { // into the local chain. Blocks older than the specified `ancientLimit` // are stored directly in the ancient store, while newer blocks are stored // in the live key-value store. - InsertReceiptChain(types.Blocks, []types.Receipts, uint64) (int, error) + InsertReceiptChain(types.Blocks, []rlp.RawValue, uint64) (int, error) // Snapshots returns the blockchain snapshot tree to paused it during sync. Snapshots() *snapshot.Tree @@ -1034,7 +1035,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state "lastnumn", last.Number, "lasthash", last.Hash(), ) blocks := make([]*types.Block, len(results)) - receipts := make([]types.Receipts, len(results)) + receipts := make([]rlp.RawValue, len(results)) for i, result := range results { blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.body()) receipts[i] = result.Receipts @@ -1051,7 +1052,7 @@ func (d *Downloader) commitPivotBlock(result *fetchResult) error { log.Debug("Committing snap sync pivot as new head", "number", block.Number(), "hash", block.Hash()) // Commit the pivot block as the new head, will require full sync from here on - if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}, d.ancientLimit); err != nil { + if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []rlp.RawValue{result.Receipts}, d.ancientLimit); err != nil { return err } if err := d.blockchain.SnapSyncCommitHead(block.Hash()); err != nil { diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 3a145b1958..ecc820fd35 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -255,23 +255,24 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et // peer in the download tester. The returned function can be used to retrieve // batches of block receipts from the particularly requested peer. func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { - blobs := eth.ServiceGetReceiptsQuery(dlp.chain, hashes) + blobs := eth.ServiceGetReceiptsQuery68(dlp.chain, hashes) - receipts := make([][]*types.Receipt, len(blobs)) + receipts := make([]types.Receipts, len(blobs)) for i, blob := range blobs { rlp.DecodeBytes(blob, &receipts[i]) } hasher := trie.NewStackTrie(nil) hashes = make([]common.Hash, len(receipts)) for i, receipt := range receipts { - hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher) + hashes[i] = types.DeriveSha(receipt, hasher) } req := ð.Request{ Peer: dlp.id, } + resp := eth.ReceiptsRLPResponse(types.EncodeBlockReceiptLists(receipts)) res := ð.Response{ Req: req, - Res: (*eth.ReceiptsResponse)(&receipts), + Res: &resp, Meta: hashes, Time: 1, Done: make(chan error, 1), // Ignore the returned status diff --git a/eth/downloader/fetchers_concurrent_receipts.go b/eth/downloader/fetchers_concurrent_receipts.go index 3169f030ba..dbea30e881 100644 --- a/eth/downloader/fetchers_concurrent_receipts.go +++ b/eth/downloader/fetchers_concurrent_receipts.go @@ -88,7 +88,7 @@ func (q *receiptQueue) request(peer *peerConnection, req *fetchRequest, resCh ch // deliver is responsible for taking a generic response packet from the concurrent // fetcher, unpacking the receipt data and delivering it to the downloader's queue. func (q *receiptQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) { - receipts := *packet.Res.(*eth.ReceiptsResponse) + receipts := *packet.Res.(*eth.ReceiptsRLPResponse) hashes := packet.Meta.([]common.Hash) // {receipt hashes} accepted, err := q.queue.DeliverReceipts(peer.id, receipts, hashes) diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go index 000ad97ca9..bd7acadfc4 100644 --- a/eth/downloader/queue.go +++ b/eth/downloader/queue.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" ) const ( @@ -69,7 +70,7 @@ type fetchResult struct { Header *types.Header Uncles []*types.Header Transactions types.Transactions - Receipts types.Receipts + Receipts rlp.RawValue Withdrawals types.Withdrawals } @@ -318,9 +319,7 @@ func (q *queue) Results(block bool) []*fetchResult { for _, uncle := range result.Uncles { size += uncle.Size() } - for _, receipt := range result.Receipts { - size += receipt.Size() - } + size += common.StorageSize(len(result.Receipts)) for _, tx := range result.Transactions { size += common.StorageSize(tx.Size()) } @@ -631,7 +630,7 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH // DeliverReceipts injects a receipt retrieval response into the results queue. // The method returns the number of transaction receipts accepted from the delivery // and also wakes any threads waiting for data delivery. -func (q *queue) DeliverReceipts(id string, receiptList [][]*types.Receipt, receiptListHashes []common.Hash) (int, error) { +func (q *queue) DeliverReceipts(id string, receiptList []rlp.RawValue, receiptListHashes []common.Hash) (int, error) { q.lock.Lock() defer q.lock.Unlock() diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go index 857ac4813a..854acf3d8f 100644 --- a/eth/downloader/queue_test.go +++ b/eth/downloader/queue_test.go @@ -358,16 +358,16 @@ func XTestDelivery(t *testing.T) { for { f, _, _ := q.ReserveReceipts(peer, rand.Intn(50)) if f != nil { - var rcs [][]*types.Receipt + var rcs []types.Receipts for _, hdr := range f.Headers { rcs = append(rcs, world.getReceipts(hdr.Number.Uint64())) } hasher := trie.NewStackTrie(nil) hashes := make([]common.Hash, len(rcs)) for i, receipt := range rcs { - hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher) + hashes[i] = types.DeriveSha(receipt, hasher) } - _, err := q.DeliverReceipts(peer.id, rcs, hashes) + _, err := q.DeliverReceipts(peer.id, types.EncodeBlockReceiptLists(rcs), hashes) if err != nil { fmt.Printf("delivered %d receipts %v\n", len(rcs), err) } diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index 122bdaeda4..85d4a33913 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -80,11 +80,8 @@ func (b *testBackend) GetReceiptsByHash(hash common.Hash) types.Receipts { return r } -func (b *testBackend) GetRawReceiptsByHash(hash common.Hash) types.Receipts { - if number := rawdb.ReadHeaderNumber(b.db, hash); number != nil { - return rawdb.ReadRawReceipts(b.db, hash, *number) - } - return nil +func (b *testBackend) GetRawReceipts(hash common.Hash, number uint64) types.Receipts { + return rawdb.ReadRawReceipts(b.db, hash, number) } func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { diff --git a/eth/handler.go b/eth/handler.go index f563b47138..033a44b3bb 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -18,15 +18,16 @@ package eth import ( "errors" + "maps" "math" "math/big" + "slices" "sync" "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" @@ -49,6 +50,9 @@ const ( // The number is referenced from the size of tx pool. txChanSize = 4096 + // chainHeadChanSize is the size of channel listening to ChainHeadEvent. + chainHeadChanSize = 128 + // txMaxBroadcastSize is the max size of a transaction that will be broadcasted. // All transactions with a higher size will be announced and need to be fetched // by the peer. @@ -104,9 +108,8 @@ type handlerConfig struct { } type handler struct { - nodeID enode.ID - networkID uint64 - forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node + nodeID enode.ID + networkID uint64 snapSync atomic.Bool // Flag whether snap sync is enabled (gets disabled if we already have blocks) synced atomic.Bool // Flag whether we're considered synchronised (enables transaction processing) @@ -120,9 +123,10 @@ type handler struct { txFetcher *fetcher.TxFetcher peers *peerSet - eventMux *event.TypeMux - txsCh chan core.NewTxsEvent - txsSub event.Subscription + eventMux *event.TypeMux + txsCh chan core.NewTxsEvent + txsSub event.Subscription + blockRange *blockRangeState requiredBlocks map[uint64]common.Hash @@ -144,7 +148,6 @@ func newHandler(config *handlerConfig) (*handler, error) { h := &handler{ nodeID: config.NodeID, networkID: config.Network, - forkFilter: forkid.NewFilter(config.Chain), eventMux: config.EventMux, database: config.Database, txpool: config.TxPool, @@ -257,14 +260,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error { } // Execute the Ethereum handshake - var ( - genesis = h.chain.Genesis() - head = h.chain.CurrentHeader() - hash = head.Hash() - number = head.Number.Uint64() - ) - forkID := forkid.NewID(h.chain.Config(), genesis, number, head.Time) - if err := peer.Handshake(h.networkID, hash, genesis.Hash(), forkID, h.forkFilter); err != nil { + if err := peer.Handshake(h.networkID, h.chain, h.blockRange.currentRange()); err != nil { peer.Log().Debug("Ethereum handshake failed", "err", err) return err } @@ -435,6 +431,11 @@ func (h *handler) Start(maxPeers int) { h.txsSub = h.txpool.SubscribeTransactions(h.txsCh, false) go h.txBroadcastLoop() + // broadcast block range + h.wg.Add(1) + h.blockRange = newBlockRangeState(h.chain, h.eventMux) + go h.blockRangeLoop(h.blockRange) + // start sync handlers h.txFetcher.Start() @@ -445,6 +446,7 @@ func (h *handler) Start(maxPeers int) { func (h *handler) Stop() { h.txsSub.Unsubscribe() // quits txBroadcastLoop + h.blockRange.stop() h.txFetcher.Stop() h.downloader.Terminate() @@ -566,3 +568,129 @@ func (h *handler) enableSyncedFeatures() { h.snapSync.Store(false) } } + +// blockRangeState holds the state of the block range update broadcasting mechanism. +type blockRangeState struct { + prev eth.BlockRangeUpdatePacket + next atomic.Pointer[eth.BlockRangeUpdatePacket] + headCh chan core.ChainHeadEvent + headSub event.Subscription + syncSub *event.TypeMuxSubscription +} + +func newBlockRangeState(chain *core.BlockChain, typeMux *event.TypeMux) *blockRangeState { + headCh := make(chan core.ChainHeadEvent, chainHeadChanSize) + headSub := chain.SubscribeChainHeadEvent(headCh) + syncSub := typeMux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{}) + st := &blockRangeState{ + headCh: headCh, + headSub: headSub, + syncSub: syncSub, + } + st.update(chain, chain.CurrentBlock()) + st.prev = *st.next.Load() + return st +} + +// blockRangeBroadcastLoop announces changes in locally-available block range to peers. +// The range to announce is the range that is available in the store, so it's not just +// about imported blocks. +func (h *handler) blockRangeLoop(st *blockRangeState) { + defer h.wg.Done() + + for { + select { + case ev := <-st.syncSub.Chan(): + if ev == nil { + continue + } + if _, ok := ev.Data.(downloader.StartEvent); ok && h.snapSync.Load() { + h.blockRangeWhileSnapSyncing(st) + } + case <-st.headCh: + st.update(h.chain, h.chain.CurrentBlock()) + if st.shouldSend() { + h.broadcastBlockRange(st) + } + case <-st.headSub.Err(): + return + } + } +} + +// blockRangeWhileSnapSyncing announces block range updates during snap sync. +// Here we poll the CurrentSnapBlock on a timer and announce updates to it. +func (h *handler) blockRangeWhileSnapSyncing(st *blockRangeState) { + tick := time.NewTicker(1 * time.Minute) + defer tick.Stop() + + for { + select { + case <-tick.C: + st.update(h.chain, h.chain.CurrentSnapBlock()) + if st.shouldSend() { + h.broadcastBlockRange(st) + } + // back to processing head block updates when sync is done + case ev := <-st.syncSub.Chan(): + if ev == nil { + continue + } + switch ev.Data.(type) { + case downloader.FailedEvent, downloader.DoneEvent: + return + } + // ignore head updates, but exit when the subscription ends + case <-st.headCh: + case <-st.headSub.Err(): + return + } + } +} + +// broadcastBlockRange sends a range update when one is due. +func (h *handler) broadcastBlockRange(state *blockRangeState) { + h.peers.lock.Lock() + peerlist := slices.Collect(maps.Values(h.peers.peers)) + h.peers.lock.Unlock() + if len(peerlist) == 0 { + return + } + msg := state.currentRange() + log.Debug("Sending BlockRangeUpdate", "peers", len(peerlist), "earliest", msg.EarliestBlock, "latest", msg.LatestBlock) + for _, p := range peerlist { + p.SendBlockRangeUpdate(msg) + } + state.prev = *state.next.Load() +} + +// update assigns the values of the next block range update from the chain. +func (st *blockRangeState) update(chain *core.BlockChain, latest *types.Header) { + earliest, _ := chain.HistoryPruningCutoff() + st.next.Store(ð.BlockRangeUpdatePacket{ + EarliestBlock: min(latest.Number.Uint64(), earliest), + LatestBlock: latest.Number.Uint64(), + LatestBlockHash: latest.Hash(), + }) +} + +// shouldSend decides whether it is time to send a block range update. We don't want to +// send these updates constantly, so they will usually only be sent every 32 blocks. +// However, there is a special case: if the range would move back, i.e. due to SetHead, we +// want to send it immediately. +func (st *blockRangeState) shouldSend() bool { + next := st.next.Load() + return next.LatestBlock < st.prev.LatestBlock || + next.LatestBlock-st.prev.LatestBlock >= 32 +} + +func (st *blockRangeState) stop() { + st.syncSub.Unsubscribe() + st.headSub.Unsubscribe() +} + +// currentRange returns the current block range. +// This is safe to call from any goroutine. +func (st *blockRangeState) currentRange() eth.BlockRangeUpdatePacket { + return *st.next.Load() +} diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index 8d572ca966..2446c5fccb 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -257,11 +256,7 @@ func testRecvTransactions(t *testing.T, protocol uint) { return eth.Handle((*ethHandler)(handler.handler), peer) }) // Run the handshake locally to avoid spinning up a source handler - var ( - genesis = handler.chain.Genesis() - head = handler.chain.CurrentBlock() - ) - if err := src.Handshake(1, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { + if err := src.Handshake(1, handler.chain, eth.BlockRangeUpdatePacket{}); err != nil { t.Fatalf("failed to run protocol handshake") } // Send the transaction to the sink and verify that it's added to the tx pool @@ -316,11 +311,7 @@ func testSendTransactions(t *testing.T, protocol uint) { return eth.Handle((*ethHandler)(handler.handler), peer) }) // Run the handshake locally to avoid spinning up a source handler - var ( - genesis = handler.chain.Genesis() - head = handler.chain.CurrentBlock() - ) - if err := sink.Handshake(1, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { + if err := sink.Handshake(1, handler.chain, eth.BlockRangeUpdatePacket{}); err != nil { t.Fatalf("failed to run protocol handshake") } // After the handshake completes, the source handler should stream the sink diff --git a/eth/peer.go b/eth/peer.go index 7618777716..5808c3a3c5 100644 --- a/eth/peer.go +++ b/eth/peer.go @@ -17,6 +17,7 @@ package eth import ( + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" ) @@ -25,6 +26,13 @@ import ( // about a connected peer. type ethPeerInfo struct { Version uint `json:"version"` // Ethereum protocol version negotiated + *peerBlockRange +} + +type peerBlockRange struct { + Earliest uint64 `json:"earliestBlock"` + Latest uint64 `json:"latestBlock"` + LatestHash common.Hash `json:"latestBlockHash"` } // ethPeer is a wrapper around eth.Peer to maintain a few extra metadata. @@ -35,9 +43,15 @@ type ethPeer struct { // info gathers and returns some `eth` protocol metadata known about a peer. func (p *ethPeer) info() *ethPeerInfo { - return ðPeerInfo{ - Version: p.Version(), + info := ðPeerInfo{Version: p.Version()} + if br := p.BlockRange(); br != nil { + info.peerBlockRange = &peerBlockRange{ + Earliest: br.EarliestBlock, + Latest: br.LatestBlock, + LatestHash: br.LatestBlockHash, + } } + return info } // snapPeerInfo represents a short summary of the `snap` sub-protocol metadata known diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go index f2a3cb0292..2467e0c713 100644 --- a/eth/protocols/eth/handler.go +++ b/eth/protocols/eth/handler.go @@ -175,12 +175,26 @@ var eth68 = map[uint64]msgHandler{ BlockHeadersMsg: handleBlockHeaders, GetBlockBodiesMsg: handleGetBlockBodies, BlockBodiesMsg: handleBlockBodies, - GetReceiptsMsg: handleGetReceipts, - ReceiptsMsg: handleReceipts, + GetReceiptsMsg: handleGetReceipts68, + ReceiptsMsg: handleReceipts[*ReceiptList68], GetPooledTransactionsMsg: handleGetPooledTransactions, PooledTransactionsMsg: handlePooledTransactions, } +var eth69 = map[uint64]msgHandler{ + TransactionsMsg: handleTransactions, + NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes, + GetBlockHeadersMsg: handleGetBlockHeaders, + BlockHeadersMsg: handleBlockHeaders, + GetBlockBodiesMsg: handleGetBlockBodies, + BlockBodiesMsg: handleBlockBodies, + GetReceiptsMsg: handleGetReceipts69, + ReceiptsMsg: handleReceipts[*ReceiptList69], + GetPooledTransactionsMsg: handleGetPooledTransactions, + PooledTransactionsMsg: handlePooledTransactions, + BlockRangeUpdateMsg: handleBlockRangeUpdate, +} + // handleMessage is invoked whenever an inbound message is received from a remote // peer. The remote connection is torn down upon returning any error. func handleMessage(backend Backend, peer *Peer) error { @@ -194,7 +208,14 @@ func handleMessage(backend Backend, peer *Peer) error { } defer msg.Discard() - var handlers = eth68 + var handlers map[uint64]msgHandler + if peer.version == ETH68 { + handlers = eth68 + } else if peer.version == ETH69 { + handlers = eth69 + } else { + return fmt.Errorf("unknown eth protocol version: %v", peer.version) + } // Track the amount of time it takes to serve the request and run the handler if metrics.Enabled() { diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index fa031d9899..2fa10dfa9d 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -529,22 +529,23 @@ func testGetBlockReceipts(t *testing.T, protocol uint) { // Collect the hashes to request, and the response to expect var ( hashes []common.Hash - receipts [][]*types.Receipt + receipts []*ReceiptList68 ) for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { block := backend.chain.GetBlockByNumber(i) - hashes = append(hashes, block.Hash()) - receipts = append(receipts, backend.chain.GetReceiptsByHash(block.Hash())) + trs := backend.chain.GetReceiptsByHash(block.Hash()) + receipts = append(receipts, NewReceiptList68(trs)) } + // Send the hash request and verify the response p2p.Send(peer.app, GetReceiptsMsg, &GetReceiptsPacket{ RequestId: 123, GetReceiptsRequest: hashes, }) - if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket{ - RequestId: 123, - ReceiptsResponse: receipts, + if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket[*ReceiptList68]{ + RequestId: 123, + List: receipts, }); err != nil { t.Errorf("receipts mismatch: %v", err) } @@ -612,10 +613,10 @@ func setup() (*testBackend, *testPeer) { } func FuzzEthProtocolHandlers(f *testing.F) { - handlers := eth68 + handlers := eth69 backend, peer := setup() f.Fuzz(func(t *testing.T, code byte, msg []byte) { - handler := handlers[uint64(code)%protocolLengths[ETH68]] + handler := handlers[uint64(code)%protocolLengths[ETH69]] if handler == nil { return } diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index fda650da1c..15ad048bcf 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -20,20 +20,25 @@ import ( "encoding/json" "errors" "fmt" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/tracker" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) +// requestTracker is a singleton tracker for eth/66 and newer request times. +var requestTracker = tracker.New(ProtocolName, 5*time.Minute) + func handleGetBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { // Decode the complex header query var query GetBlockHeadersPacket if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } response := ServiceGetBlockHeadersQuery(backend.Chain(), query.GetBlockHeadersRequest, peer) return peer.ReplyBlockHeadersRLP(query.RequestId, response) @@ -216,7 +221,7 @@ func handleGetBlockBodies(backend Backend, msg Decoder, peer *Peer) error { // Decode the block body retrieval message var query GetBlockBodiesPacket if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } response := ServiceGetBlockBodiesQuery(backend.Chain(), query.GetBlockBodiesRequest) return peer.ReplyBlockBodiesRLP(query.RequestId, response) @@ -243,19 +248,29 @@ func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesRequ return bodies } -func handleGetReceipts(backend Backend, msg Decoder, peer *Peer) error { +func handleGetReceipts68(backend Backend, msg Decoder, peer *Peer) error { // Decode the block receipts retrieval message var query GetReceiptsPacket if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } - response := ServiceGetReceiptsQuery(backend.Chain(), query.GetReceiptsRequest) + response := ServiceGetReceiptsQuery68(backend.Chain(), query.GetReceiptsRequest) return peer.ReplyReceiptsRLP(query.RequestId, response) } -// ServiceGetReceiptsQuery assembles the response to a receipt query. It is +func handleGetReceipts69(backend Backend, msg Decoder, peer *Peer) error { + // Decode the block receipts retrieval message + var query GetReceiptsPacket + if err := msg.Decode(&query); err != nil { + return err + } + response := serviceGetReceiptsQuery69(backend.Chain(), query.GetReceiptsRequest) + return peer.ReplyReceiptsRLP(query.RequestId, response) +} + +// ServiceGetReceiptsQuery68 assembles the response to a receipt query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue { +func ServiceGetReceiptsQuery68(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue { // Gather state data until the fetch or network limits is reached var ( bytes int @@ -267,19 +282,62 @@ func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) [ break } // Retrieve the requested block's receipts - results := chain.GetReceiptsByHash(hash) + results := chain.GetReceiptsRLP(hash) if results == nil { if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { continue } + } else { + body := chain.GetBodyRLP(hash) + if body == nil { + continue + } + var err error + results, err = blockReceiptsToNetwork68(results, body) + if err != nil { + log.Error("Error in block receipts conversion", "hash", hash, "err", err) + continue + } } - // If known, encode and queue for response packet - if encoded, err := rlp.EncodeToBytes(results); err != nil { - log.Error("Failed to encode receipt", "err", err) + receipts = append(receipts, results) + bytes += len(results) + } + return receipts +} + +// serviceGetReceiptsQuery69 assembles the response to a receipt query. +// It does not send the bloom filters for the receipts +func serviceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue { + // Gather state data until the fetch or network limits is reached + var ( + bytes int + receipts []rlp.RawValue + ) + for lookups, hash := range query { + if bytes >= softResponseLimit || len(receipts) >= maxReceiptsServe || + lookups >= 2*maxReceiptsServe { + break + } + // Retrieve the requested block's receipts + results := chain.GetReceiptsRLP(hash) + if results == nil { + if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { + continue + } } else { - receipts = append(receipts, encoded) - bytes += len(encoded) + body := chain.GetBodyRLP(hash) + if body == nil { + continue + } + var err error + results, err = blockReceiptsToNetwork69(results, body) + if err != nil { + log.Error("Error in block receipts conversion", "hash", hash, "err", err) + continue + } } + receipts = append(receipts, results) + bytes += len(results) } return receipts } @@ -296,7 +354,7 @@ func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { // A batch of headers arrived to one of our previous requests res := new(BlockHeadersPacket) if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } metadata := func() interface{} { hashes := make([]common.Hash, len(res.BlockHeadersRequest)) @@ -316,7 +374,7 @@ func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error { // A batch of block bodies arrived to one of our previous requests res := new(BlockBodiesPacket) if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } metadata := func() interface{} { var ( @@ -341,24 +399,35 @@ func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error { }, metadata) } -func handleReceipts(backend Backend, msg Decoder, peer *Peer) error { +func handleReceipts[L ReceiptsList](backend Backend, msg Decoder, peer *Peer) error { // A batch of receipts arrived to one of our previous requests - res := new(ReceiptsPacket) + res := new(ReceiptsPacket[L]) if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } + // Assign temporary hashing buffer to each list item, the same buffer is shared + // between all receipt list instances. + buffers := new(receiptListBuffers) + for i := range res.List { + res.List[i].setBuffers(buffers) + } + metadata := func() interface{} { hasher := trie.NewStackTrie(nil) - hashes := make([]common.Hash, len(res.ReceiptsResponse)) - for i, receipt := range res.ReceiptsResponse { - hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher) + hashes := make([]common.Hash, len(res.List)) + for i := range res.List { + hashes[i] = types.DeriveSha(res.List[i], hasher) } return hashes } + var enc ReceiptsRLPResponse + for i := range res.List { + enc = append(enc, res.List[i].EncodeForStorage()) + } return peer.dispatchResponse(&Response{ id: res.RequestId, code: ReceiptsMsg, - Res: &res.ReceiptsResponse, + Res: &enc, }, metadata) } @@ -370,10 +439,10 @@ func handleNewPooledTransactionHashes(backend Backend, msg Decoder, peer *Peer) } ann := new(NewPooledTransactionHashesPacket) if err := msg.Decode(ann); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } if len(ann.Hashes) != len(ann.Types) || len(ann.Hashes) != len(ann.Sizes) { - return fmt.Errorf("%w: message %v: invalid len of fields: %v %v %v", errDecode, msg, len(ann.Hashes), len(ann.Types), len(ann.Sizes)) + return fmt.Errorf("NewPooledTransactionHashes: invalid len of fields in %v %v %v", len(ann.Hashes), len(ann.Types), len(ann.Sizes)) } // Schedule all the unknown hashes for retrieval for _, hash := range ann.Hashes { @@ -386,7 +455,7 @@ func handleGetPooledTransactions(backend Backend, msg Decoder, peer *Peer) error // Decode the pooled transactions retrieval message var query GetPooledTransactionsPacket if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } hashes, txs := answerGetPooledTransactions(backend, query.GetPooledTransactionsRequest) return peer.ReplyPooledTransactionsRLP(query.RequestId, hashes, txs) @@ -423,12 +492,12 @@ func handleTransactions(backend Backend, msg Decoder, peer *Peer) error { // Transactions can be processed, parse all of them and deliver to the pool var txs TransactionsPacket if err := msg.Decode(&txs); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } for i, tx := range txs { // Validate and mark the remote transaction if tx == nil { - return fmt.Errorf("%w: transaction %d is nil", errDecode, i) + return fmt.Errorf("Transactions: transaction %d is nil", i) } peer.markTransaction(tx.Hash()) } @@ -443,12 +512,12 @@ func handlePooledTransactions(backend Backend, msg Decoder, peer *Peer) error { // Transactions can be processed, parse all of them and deliver to the pool var txs PooledTransactionsPacket if err := msg.Decode(&txs); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + return err } for i, tx := range txs.PooledTransactionsResponse { // Validate and mark the remote transaction if tx == nil { - return fmt.Errorf("%w: transaction %d is nil", errDecode, i) + return fmt.Errorf("PooledTransactions: transaction %d is nil", i) } peer.markTransaction(tx.Hash()) } @@ -456,3 +525,16 @@ func handlePooledTransactions(backend Backend, msg Decoder, peer *Peer) error { return backend.Handle(peer, &txs.PooledTransactionsResponse) } + +func handleBlockRangeUpdate(backend Backend, msg Decoder, peer *Peer) error { + var update BlockRangeUpdatePacket + if err := msg.Decode(&update); err != nil { + return err + } + if err := update.Validate(); err != nil { + return err + } + // We don't do anything with these messages for now, just store them on the peer. + peer.lastRange.Store(&update) + return nil +} diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go index 0b6f110e3d..824e49fb2b 100644 --- a/eth/protocols/eth/handshake.go +++ b/eth/protocols/eth/handshake.go @@ -19,10 +19,10 @@ package eth import ( "errors" "fmt" - "math/big" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p" @@ -36,44 +36,122 @@ const ( // Handshake executes the eth protocol handshake, negotiating version number, // network IDs, difficulties, head and genesis blocks. -func (p *Peer) Handshake(network uint64, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error { - // Send out own handshake in a new thread +func (p *Peer) Handshake(networkID uint64, chain *core.BlockChain, rangeMsg BlockRangeUpdatePacket) error { + switch p.version { + case ETH69: + return p.handshake69(networkID, chain, rangeMsg) + case ETH68: + return p.handshake68(networkID, chain) + default: + return errors.New("unsupported protocol version") + } +} + +func (p *Peer) handshake68(networkID uint64, chain *core.BlockChain) error { + var ( + genesis = chain.Genesis() + latest = chain.CurrentBlock() + forkID = forkid.NewID(chain.Config(), genesis, latest.Number.Uint64(), latest.Time) + forkFilter = forkid.NewFilter(chain) + ) errc := make(chan error, 2) + go func() { + pkt := &StatusPacket68{ + ProtocolVersion: uint32(p.version), + NetworkID: networkID, + Head: latest.Hash(), + Genesis: genesis.Hash(), + ForkID: forkID, + } + errc <- p2p.Send(p.rw, StatusMsg, pkt) + }() + var status StatusPacket68 // safe to read after two values have been received from errc + go func() { + errc <- p.readStatus68(networkID, &status, genesis.Hash(), forkFilter) + }() + + return waitForHandshake(errc, p) +} + +func (p *Peer) readStatus68(networkID uint64, status *StatusPacket68, genesis common.Hash, forkFilter forkid.Filter) error { + if err := p.readStatusMsg(status); err != nil { + return err + } + if status.NetworkID != networkID { + return fmt.Errorf("%w: %d (!= %d)", errNetworkIDMismatch, status.NetworkID, networkID) + } + if uint(status.ProtocolVersion) != p.version { + return fmt.Errorf("%w: %d (!= %d)", errProtocolVersionMismatch, status.ProtocolVersion, p.version) + } + if status.Genesis != genesis { + return fmt.Errorf("%w: %x (!= %x)", errGenesisMismatch, status.Genesis, genesis) + } + if err := forkFilter(status.ForkID); err != nil { + return fmt.Errorf("%w: %v", errForkIDRejected, err) + } + return nil +} - var status StatusPacket // safe to read after two values have been received from errc +func (p *Peer) handshake69(networkID uint64, chain *core.BlockChain, rangeMsg BlockRangeUpdatePacket) error { + var ( + genesis = chain.Genesis() + latest = chain.CurrentBlock() + forkID = forkid.NewID(chain.Config(), genesis, latest.Number.Uint64(), latest.Time) + forkFilter = forkid.NewFilter(chain) + ) + errc := make(chan error, 2) go func() { - errc <- p2p.Send(p.rw, StatusMsg, &StatusPacket{ + pkt := &StatusPacket69{ ProtocolVersion: uint32(p.version), - NetworkID: network, - TD: new(big.Int), // unknown for post-merge tail=pruned networks - Head: head, - Genesis: genesis, + NetworkID: networkID, + Genesis: genesis.Hash(), ForkID: forkID, - }) + EarliestBlock: rangeMsg.EarliestBlock, + LatestBlock: rangeMsg.LatestBlock, + LatestBlockHash: rangeMsg.LatestBlockHash, + } + errc <- p2p.Send(p.rw, StatusMsg, pkt) }() + var status StatusPacket69 // safe to read after two values have been received from errc go func() { - errc <- p.readStatus(network, &status, genesis, forkFilter) + errc <- p.readStatus69(networkID, &status, genesis.Hash(), forkFilter) }() - timeout := time.NewTimer(handshakeTimeout) - defer timeout.Stop() - for i := 0; i < 2; i++ { - select { - case err := <-errc: - if err != nil { - markError(p, err) - return err - } - case <-timeout.C: - markError(p, p2p.DiscReadTimeout) - return p2p.DiscReadTimeout - } + + return waitForHandshake(errc, p) +} + +func (p *Peer) readStatus69(networkID uint64, status *StatusPacket69, genesis common.Hash, forkFilter forkid.Filter) error { + if err := p.readStatusMsg(status); err != nil { + return err + } + if status.NetworkID != networkID { + return fmt.Errorf("%w: %d (!= %d)", errNetworkIDMismatch, status.NetworkID, networkID) + } + if uint(status.ProtocolVersion) != p.version { + return fmt.Errorf("%w: %d (!= %d)", errProtocolVersionMismatch, status.ProtocolVersion, p.version) + } + if status.Genesis != genesis { + return fmt.Errorf("%w: %x (!= %x)", errGenesisMismatch, status.Genesis, genesis) + } + if err := forkFilter(status.ForkID); err != nil { + return fmt.Errorf("%w: %v", errForkIDRejected, err) + } + // Handle initial block range. + initRange := &BlockRangeUpdatePacket{ + EarliestBlock: status.EarliestBlock, + LatestBlock: status.LatestBlock, + LatestBlockHash: status.LatestBlockHash, + } + if err := initRange.Validate(); err != nil { + return fmt.Errorf("%w: %v", errInvalidBlockRange, err) } + p.lastRange.Store(initRange) return nil } -// readStatus reads the remote handshake message. -func (p *Peer) readStatus(network uint64, status *StatusPacket, genesis common.Hash, forkFilter forkid.Filter) error { +// readStatusMsg reads the first message on the connection. +func (p *Peer) readStatusMsg(dst any) error { msg, err := p.rw.ReadMsg() if err != nil { return err @@ -84,21 +162,26 @@ func (p *Peer) readStatus(network uint64, status *StatusPacket, genesis common.H if msg.Size > maxMessageSize { return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize) } - // Decode the handshake and make sure everything matches - if err := msg.Decode(&status); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - if status.NetworkID != network { - return fmt.Errorf("%w: %d (!= %d)", errNetworkIDMismatch, status.NetworkID, network) - } - if uint(status.ProtocolVersion) != p.version { - return fmt.Errorf("%w: %d (!= %d)", errProtocolVersionMismatch, status.ProtocolVersion, p.version) - } - if status.Genesis != genesis { - return fmt.Errorf("%w: %x (!= %x)", errGenesisMismatch, status.Genesis, genesis) + if err := msg.Decode(dst); err != nil { + return err } - if err := forkFilter(status.ForkID); err != nil { - return fmt.Errorf("%w: %v", errForkIDRejected, err) + return nil +} + +func waitForHandshake(errc <-chan error, p *Peer) error { + timeout := time.NewTimer(handshakeTimeout) + defer timeout.Stop() + for range 2 { + select { + case err := <-errc: + if err != nil { + markError(p, err) + return err + } + case <-timeout.C: + markError(p, p2p.DiscReadTimeout) + return p2p.DiscReadTimeout + } } return nil } @@ -124,3 +207,14 @@ func markError(p *Peer, err error) { m.peerError.Mark(1) } } + +// Validate checks basic validity of a block range announcement. +func (p *BlockRangeUpdatePacket) Validate() error { + if p.EarliestBlock > p.LatestBlock { + return errors.New("earliest > latest") + } + if p.LatestBlockHash == (common.Hash{}) { + return errors.New("zero latest hash") + } + return nil +} diff --git a/eth/protocols/eth/handshake_test.go b/eth/protocols/eth/handshake_test.go index 1d1de3ec16..2fab3ea5a8 100644 --- a/eth/protocols/eth/handshake_test.go +++ b/eth/protocols/eth/handshake_test.go @@ -52,19 +52,19 @@ func testHandshake(t *testing.T, protocol uint) { want: errNoStatusMsg, }, { - code: StatusMsg, data: StatusPacket{10, 1, new(big.Int), head.Hash(), genesis.Hash(), forkID}, + code: StatusMsg, data: StatusPacket68{10, 1, new(big.Int), head.Hash(), genesis.Hash(), forkID}, want: errProtocolVersionMismatch, }, { - code: StatusMsg, data: StatusPacket{uint32(protocol), 999, new(big.Int), head.Hash(), genesis.Hash(), forkID}, + code: StatusMsg, data: StatusPacket68{uint32(protocol), 999, new(big.Int), head.Hash(), genesis.Hash(), forkID}, want: errNetworkIDMismatch, }, { - code: StatusMsg, data: StatusPacket{uint32(protocol), 1, new(big.Int), head.Hash(), common.Hash{3}, forkID}, + code: StatusMsg, data: StatusPacket68{uint32(protocol), 1, new(big.Int), head.Hash(), common.Hash{3}, forkID}, want: errGenesisMismatch, }, { - code: StatusMsg, data: StatusPacket{uint32(protocol), 1, new(big.Int), head.Hash(), genesis.Hash(), forkid.ID{Hash: [4]byte{0x00, 0x01, 0x02, 0x03}}}, + code: StatusMsg, data: StatusPacket68{uint32(protocol), 1, new(big.Int), head.Hash(), genesis.Hash(), forkid.ID{Hash: [4]byte{0x00, 0x01, 0x02, 0x03}}}, want: errForkIDRejected, }, } @@ -80,7 +80,7 @@ func testHandshake(t *testing.T, protocol uint) { // Send the junk test with one peer, check the handshake failure go p2p.Send(app, test.code, test.data) - err := peer.Handshake(1, head.Hash(), genesis.Hash(), forkID, forkid.NewFilter(backend.chain)) + err := peer.Handshake(1, backend.chain, BlockRangeUpdatePacket{}) if err == nil { t.Errorf("test %d: protocol returned nil error, want %q", i, test.want) } else if !errors.Is(err, test.want) { diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index 31a35eb186..40c54a3570 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -18,6 +18,7 @@ package eth import ( "math/rand" + "sync/atomic" mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/common" @@ -47,6 +48,7 @@ type Peer struct { *p2p.Peer // The embedded P2P package peer rw p2p.MsgReadWriter // Input/output streams for snap version uint // Protocol version negotiated + lastRange atomic.Pointer[BlockRangeUpdatePacket] txpool TxPool // Transaction pool used by the broadcasters for liveness checks knownTxs *knownCache // Set of transaction hashes known to be known by this peer @@ -102,6 +104,12 @@ func (p *Peer) Version() uint { return p.version } +// BlockRange returns the latest announced block range. +// This will be nil for peers below protocol version eth/69. +func (p *Peer) BlockRange() *BlockRangeUpdatePacket { + return p.lastRange.Load() +} + // KnownTransaction returns whether peer is known to already have a transaction. func (p *Peer) KnownTransaction(hash common.Hash) bool { return p.knownTxs.Contains(hash) @@ -343,6 +351,14 @@ func (p *Peer) RequestTxs(hashes []common.Hash) error { }) } +// SendBlockRangeUpdate sends a notification about our available block range to the peer. +func (p *Peer) SendBlockRangeUpdate(msg BlockRangeUpdatePacket) error { + if p.version < ETH69 { + return nil + } + return p2p.Send(p.rw, BlockRangeUpdateMsg, &msg) +} + // knownCache is a cache for known hashes. type knownCache struct { hashes mapset.Set[common.Hash] diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index aeef4330ff..7c41e7a996 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -31,6 +31,7 @@ import ( // Constants to match up protocol versions and messages const ( ETH68 = 68 + ETH69 = 69 ) // ProtocolName is the official short name of the `eth` protocol used during @@ -39,11 +40,11 @@ const ProtocolName = "eth" // ProtocolVersions are the supported versions of the `eth` protocol (first // is primary). -var ProtocolVersions = []uint{ETH68} +var ProtocolVersions = []uint{ETH69, ETH68} // protocolLengths are the number of implemented message corresponding to // different protocol versions. -var protocolLengths = map[uint]uint64{ETH68: 17} +var protocolLengths = map[uint]uint64{ETH68: 17, ETH69: 18} // maxMessageSize is the maximum cap on the size of a protocol message. const maxMessageSize = 10 * 1024 * 1024 @@ -62,17 +63,19 @@ const ( PooledTransactionsMsg = 0x0a GetReceiptsMsg = 0x0f ReceiptsMsg = 0x10 + BlockRangeUpdateMsg = 0x11 ) var ( - errNoStatusMsg = errors.New("no status message") errMsgTooLarge = errors.New("message too long") - errDecode = errors.New("invalid message") errInvalidMsgCode = errors.New("invalid message code") errProtocolVersionMismatch = errors.New("protocol version mismatch") - errNetworkIDMismatch = errors.New("network ID mismatch") - errGenesisMismatch = errors.New("genesis mismatch") - errForkIDRejected = errors.New("fork ID rejected") + // handshake errors + errNoStatusMsg = errors.New("no status message") + errNetworkIDMismatch = errors.New("network ID mismatch") + errGenesisMismatch = errors.New("genesis mismatch") + errForkIDRejected = errors.New("fork ID rejected") + errInvalidBlockRange = errors.New("invalid block range in status") ) // Packet represents a p2p message in the `eth` protocol. @@ -82,7 +85,7 @@ type Packet interface { } // StatusPacket is the network packet for the status message. -type StatusPacket struct { +type StatusPacket68 struct { ProtocolVersion uint32 NetworkID uint64 TD *big.Int @@ -91,6 +94,18 @@ type StatusPacket struct { ForkID forkid.ID } +// StatusPacket69 is the network packet for the status message. +type StatusPacket69 struct { + ProtocolVersion uint32 + NetworkID uint64 + Genesis common.Hash + ForkID forkid.ID + // initial available block range + EarliestBlock uint64 + LatestBlock uint64 + LatestBlockHash common.Hash +} + // NewBlockHashesPacket is the network packet for the block announcements. type NewBlockHashesPacket []struct { Hash common.Hash // Hash of one particular block being announced @@ -250,13 +265,21 @@ type GetReceiptsPacket struct { } // ReceiptsResponse is the network packet for block receipts distribution. -type ReceiptsResponse [][]*types.Receipt +type ReceiptsResponse []types.Receipts + +// ReceiptsList is a type constraint for block receceipt list types. +type ReceiptsList interface { + *ReceiptList68 | *ReceiptList69 + setBuffers(*receiptListBuffers) + EncodeForStorage() rlp.RawValue + types.DerivableList +} // ReceiptsPacket is the network packet for block receipts distribution with // request ID wrapping. -type ReceiptsPacket struct { +type ReceiptsPacket[L ReceiptsList] struct { RequestId uint64 - ReceiptsResponse + List []L } // ReceiptsRLPResponse is used for receipts, when we already have it encoded @@ -304,8 +327,18 @@ type PooledTransactionsRLPPacket struct { PooledTransactionsRLPResponse } -func (*StatusPacket) Name() string { return "Status" } -func (*StatusPacket) Kind() byte { return StatusMsg } +// BlockRangeUpdatePacket is an announcement of the node's available block range. +type BlockRangeUpdatePacket struct { + EarliestBlock uint64 + LatestBlock uint64 + LatestBlockHash common.Hash +} + +func (*StatusPacket68) Name() string { return "Status" } +func (*StatusPacket68) Kind() byte { return StatusMsg } + +func (*StatusPacket69) Name() string { return "Status" } +func (*StatusPacket69) Kind() byte { return StatusMsg } func (*NewBlockHashesPacket) Name() string { return "NewBlockHashes" } func (*NewBlockHashesPacket) Kind() byte { return NewBlockHashesMsg } @@ -342,3 +375,9 @@ func (*GetReceiptsRequest) Kind() byte { return GetReceiptsMsg } func (*ReceiptsResponse) Name() string { return "Receipts" } func (*ReceiptsResponse) Kind() byte { return ReceiptsMsg } + +func (*ReceiptsRLPResponse) Name() string { return "Receipts" } +func (*ReceiptsRLPResponse) Kind() byte { return ReceiptsMsg } + +func (*BlockRangeUpdatePacket) Name() string { return "BlockRangeUpdate" } +func (*BlockRangeUpdatePacket) Kind() byte { return BlockRangeUpdateMsg } diff --git a/eth/protocols/eth/protocol_test.go b/eth/protocols/eth/protocol_test.go index bc2545dea2..8a2559a6c5 100644 --- a/eth/protocols/eth/protocol_test.go +++ b/eth/protocols/eth/protocol_test.go @@ -75,7 +75,7 @@ func TestEmptyMessages(t *testing.T) { // All empty messages encodes to the same format want := common.FromHex("c4820457c0") - for i, msg := range []interface{}{ + for i, msg := range []any{ // Headers GetBlockHeadersPacket{1111, nil}, BlockHeadersPacket{1111, nil}, @@ -85,7 +85,6 @@ func TestEmptyMessages(t *testing.T) { BlockBodiesRLPPacket{1111, nil}, // Receipts GetReceiptsPacket{1111, nil}, - ReceiptsPacket{1111, nil}, // Transactions GetPooledTransactionsPacket{1111, nil}, PooledTransactionsPacket{1111, nil}, @@ -99,7 +98,8 @@ func TestEmptyMessages(t *testing.T) { BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{})}, // Receipts GetReceiptsPacket{1111, GetReceiptsRequest([]common.Hash{})}, - ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{})}, + ReceiptsPacket[*ReceiptList68]{1111, []*ReceiptList68{}}, + ReceiptsPacket[*ReceiptList69]{1111, []*ReceiptList69{}}, // Transactions GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest([]common.Hash{})}, PooledTransactionsPacket{1111, PooledTransactionsResponse([]*types.Transaction{})}, @@ -168,7 +168,7 @@ func TestMessages(t *testing.T) { receipts = []*types.Receipt{ { Status: types.ReceiptStatusFailed, - CumulativeGasUsed: 1, + CumulativeGasUsed: 333, Logs: []*types.Log{ { Address: common.BytesToAddress([]byte{0x11}), @@ -176,11 +176,21 @@ func TestMessages(t *testing.T) { Data: []byte{0x01, 0x00, 0xff}, }, }, - TxHash: hashes[0], - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, + }, + { + Status: types.ReceiptStatusSuccessful, + CumulativeGasUsed: 444, + Logs: []*types.Log{ + { + Address: common.BytesToAddress([]byte{0x22}), + Topics: []common.Hash{common.HexToHash("05668"), common.HexToHash("9773")}, + Data: []byte{0x02, 0x0f, 0x0f, 0x0f, 0x06, 0x08}, + }, + }, }, } + miniDeriveFields(receipts[0], 0) + miniDeriveFields(receipts[1], 1) rlpData, err := rlp.EncodeToBytes(receipts) if err != nil { t.Fatal(err) @@ -221,12 +231,17 @@ func TestMessages(t *testing.T) { common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), }, { - ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{receipts})}, - common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"), + ReceiptsPacket[*ReceiptList68]{1111, []*ReceiptList68{NewReceiptList68(receipts)}}, + common.FromHex("f902e6820457f902e0f902ddf901688082014db9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000004000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ffb9016f01f9016b018201bcb9010000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000000000000000040000000000000000000000000004000000000000000000000000000000000000000000000000000000008000400000000000000000000000000000000000000000000000000000000000000000000000000000040f862f860940000000000000000000000000000000000000022f842a00000000000000000000000000000000000000000000000000000000000005668a0000000000000000000000000000000000000000000000000000000000000977386020f0f0f0608"), }, { + // Identical to the eth/68 encoding above. ReceiptsRLPPacket{1111, ReceiptsRLPResponse([]rlp.RawValue{receiptsRlp})}, - common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"), + common.FromHex("f902e6820457f902e0f902ddf901688082014db9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000004000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ffb9016f01f9016b018201bcb9010000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000000000000000040000000000000000000000000004000000000000000000000000000000000000000000000000000000008000400000000000000000000000000000000000000000000000000000000000000000000000000000040f862f860940000000000000000000000000000000000000022f842a00000000000000000000000000000000000000000000000000000000000005668a0000000000000000000000000000000000000000000000000000000000000977386020f0f0f0608"), + }, + { + ReceiptsPacket[*ReceiptList69]{1111, []*ReceiptList69{NewReceiptList69(receipts)}}, + common.FromHex("f8da820457f8d5f8d3f866808082014df85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff86901018201bcf862f860940000000000000000000000000000000000000022f842a00000000000000000000000000000000000000000000000000000000000005668a0000000000000000000000000000000000000000000000000000000000000977386020f0f0f0608"), }, { GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest(hashes)}, diff --git a/eth/protocols/eth/receipt.go b/eth/protocols/eth/receipt.go new file mode 100644 index 0000000000..45c4766b17 --- /dev/null +++ b/eth/protocols/eth/receipt.go @@ -0,0 +1,462 @@ +// Copyright 2024 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 . + +package eth + +import ( + "bytes" + "fmt" + "io" + "iter" + "math/big" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" +) + +// This is just a sanity limit for the size of a single receipt. +const maxReceiptSize = 16 * 1024 * 1024 + +// Receipt is the representation of receipts for networking purposes. +type Receipt struct { + TxType byte + PostStateOrStatus []byte + GasUsed uint64 + Logs rlp.RawValue +} + +func newReceipt(tr *types.Receipt) Receipt { + r := Receipt{TxType: tr.Type, GasUsed: tr.CumulativeGasUsed} + if tr.PostState != nil { + r.PostStateOrStatus = tr.PostState + } else { + r.PostStateOrStatus = new(big.Int).SetUint64(tr.Status).Bytes() + } + r.Logs, _ = rlp.EncodeToBytes(tr.Logs) + return r +} + +// decode68 parses a receipt in the eth/68 network encoding. +func (r *Receipt) decode68(buf *receiptListBuffers, s *rlp.Stream) error { + k, size, err := s.Kind() + if err != nil { + return err + } + + *r = Receipt{} + if k == rlp.List { + // Legacy receipt. + return r.decodeInnerList(s, false, true) + } + // Typed receipt. + if size < 2 || size > maxReceiptSize { + return fmt.Errorf("invalid receipt size %d", size) + } + buf.tmp.Reset() + buf.tmp.Grow(int(size)) + payload := buf.tmp.Bytes()[:int(size)] + if err := s.ReadBytes(payload); err != nil { + return err + } + r.TxType = payload[0] + s2 := rlp.NewStream(bytes.NewReader(payload[1:]), 0) + return r.decodeInnerList(s2, false, true) +} + +// decode69 parses a receipt in the eth/69 network encoding. +func (r *Receipt) decode69(s *rlp.Stream) error { + *r = Receipt{} + return r.decodeInnerList(s, true, false) +} + +// decodeDatabase parses a receipt in the basic database encoding. +func (r *Receipt) decodeDatabase(txType byte, s *rlp.Stream) error { + *r = Receipt{TxType: txType} + return r.decodeInnerList(s, false, false) +} + +func (r *Receipt) decodeInnerList(s *rlp.Stream, readTxType, readBloom bool) error { + _, err := s.List() + if err != nil { + return err + } + if readTxType { + r.TxType, err = s.Uint8() + if err != nil { + return fmt.Errorf("invalid txType: %w", err) + } + } + r.PostStateOrStatus, err = s.Bytes() + if err != nil { + return fmt.Errorf("invalid postStateOrStatus: %w", err) + } + r.GasUsed, err = s.Uint64() + if err != nil { + return fmt.Errorf("invalid gasUsed: %w", err) + } + if readBloom { + var b types.Bloom + if err := s.ReadBytes(b[:]); err != nil { + return fmt.Errorf("invalid bloom: %v", err) + } + } + r.Logs, err = s.Raw() + if err != nil { + return fmt.Errorf("invalid logs: %w", err) + } + return s.ListEnd() +} + +// encodeForStorage produces the the storage encoding, i.e. the result matches +// the RLP encoding of types.ReceiptForStorage. +func (r *Receipt) encodeForStorage(w *rlp.EncoderBuffer) { + list := w.List() + w.WriteBytes(r.PostStateOrStatus) + w.WriteUint64(r.GasUsed) + w.Write(r.Logs) + w.ListEnd(list) +} + +// encodeForNetwork68 produces the eth/68 network protocol encoding of a receipt. +// Note this recomputes the bloom filter of the receipt. +func (r *Receipt) encodeForNetwork68(buf *receiptListBuffers, w *rlp.EncoderBuffer) { + writeInner := func(w *rlp.EncoderBuffer) { + list := w.List() + w.WriteBytes(r.PostStateOrStatus) + w.WriteUint64(r.GasUsed) + bloom := r.bloom(&buf.bloom) + w.WriteBytes(bloom[:]) + w.Write(r.Logs) + w.ListEnd(list) + } + + if r.TxType == 0 { + writeInner(w) + } else { + buf.tmp.Reset() + buf.tmp.WriteByte(r.TxType) + buf.enc.Reset(&buf.tmp) + writeInner(&buf.enc) + buf.enc.Flush() + w.WriteBytes(buf.tmp.Bytes()) + } +} + +// encodeForNetwork69 produces the eth/69 network protocol encoding of a receipt. +func (r *Receipt) encodeForNetwork69(w *rlp.EncoderBuffer) { + list := w.List() + w.WriteUint64(uint64(r.TxType)) + w.WriteBytes(r.PostStateOrStatus) + w.WriteUint64(r.GasUsed) + w.Write(r.Logs) + w.ListEnd(list) +} + +// encodeForHash encodes a receipt for the block receiptsRoot derivation. +func (r *Receipt) encodeForHash(buf *receiptListBuffers, out *bytes.Buffer) { + // For typed receipts, add the tx type. + if r.TxType != 0 { + out.WriteByte(r.TxType) + } + // Encode list = [postStateOrStatus, gasUsed, bloom, logs]. + w := &buf.enc + w.Reset(out) + l := w.List() + w.WriteBytes(r.PostStateOrStatus) + w.WriteUint64(r.GasUsed) + bloom := r.bloom(&buf.bloom) + w.WriteBytes(bloom[:]) + w.Write(r.Logs) + w.ListEnd(l) + w.Flush() +} + +// bloom computes the bloom filter of the receipt. +// Note this doesn't check the validity of encoding, and will produce an invalid filter +// for invalid input. This is acceptable for the purpose of this function, which is +// recomputing the receipt hash. +func (r *Receipt) bloom(buffer *[6]byte) types.Bloom { + var b types.Bloom + logsIter, err := rlp.NewListIterator(r.Logs) + if err != nil { + return b + } + for logsIter.Next() { + log, _, _ := rlp.SplitList(logsIter.Value()) + address, log, _ := rlp.SplitString(log) + b.AddWithBuffer(address, buffer) + topicsIter, err := rlp.NewListIterator(log) + if err != nil { + return b + } + for topicsIter.Next() { + topic, _, _ := rlp.SplitString(topicsIter.Value()) + b.AddWithBuffer(topic, buffer) + } + } + return b +} + +type receiptListBuffers struct { + enc rlp.EncoderBuffer + bloom [6]byte + tmp bytes.Buffer +} + +func initBuffers(buf **receiptListBuffers) { + if *buf == nil { + *buf = new(receiptListBuffers) + } +} + +// encodeForStorage encodes a list of receipts for the database. +func (buf *receiptListBuffers) encodeForStorage(rs []Receipt) rlp.RawValue { + var out bytes.Buffer + w := &buf.enc + w.Reset(&out) + outer := w.List() + for _, receipts := range rs { + receipts.encodeForStorage(w) + } + w.ListEnd(outer) + w.Flush() + return out.Bytes() +} + +// ReceiptList68 is a block receipt list as downloaded by eth/68. +// This also implements types.DerivableList for validation purposes. +type ReceiptList68 struct { + buf *receiptListBuffers + items []Receipt +} + +// NewReceiptList68 creates a receipt list. +// This is slow, and exists for testing purposes. +func NewReceiptList68(trs []*types.Receipt) *ReceiptList68 { + rl := &ReceiptList68{items: make([]Receipt, len(trs))} + for i, tr := range trs { + rl.items[i] = newReceipt(tr) + } + return rl +} + +func blockReceiptsToNetwork68(blockReceipts, blockBody rlp.RawValue) ([]byte, error) { + txTypesIter, err := txTypesInBody(blockBody) + if err != nil { + return nil, fmt.Errorf("invalid block body: %v", err) + } + nextTxType, stopTxTypes := iter.Pull(txTypesIter) + defer stopTxTypes() + + var ( + out bytes.Buffer + buf receiptListBuffers + ) + blockReceiptIter, _ := rlp.NewListIterator(blockReceipts) + innerReader := bytes.NewReader(nil) + innerStream := rlp.NewStream(innerReader, 0) + w := rlp.NewEncoderBuffer(&out) + outer := w.List() + for i := 0; blockReceiptIter.Next(); i++ { + content := blockReceiptIter.Value() + innerReader.Reset(content) + innerStream.Reset(innerReader, uint64(len(content))) + var r Receipt + txType, _ := nextTxType() + if err := r.decodeDatabase(txType, innerStream); err != nil { + return nil, fmt.Errorf("invalid database receipt %d: %v", i, err) + } + r.encodeForNetwork68(&buf, &w) + } + w.ListEnd(outer) + w.Flush() + return out.Bytes(), nil +} + +// setBuffers implements ReceiptsList. +func (rl *ReceiptList68) setBuffers(buf *receiptListBuffers) { + rl.buf = buf +} + +// EncodeForStorage encodes the receipts for storage into the database. +func (rl *ReceiptList68) EncodeForStorage() rlp.RawValue { + initBuffers(&rl.buf) + return rl.buf.encodeForStorage(rl.items) +} + +// Len implements types.DerivableList. +func (rl *ReceiptList68) Len() int { + return len(rl.items) +} + +// EncodeIndex implements types.DerivableList. +func (rl *ReceiptList68) EncodeIndex(i int, out *bytes.Buffer) { + initBuffers(&rl.buf) + rl.items[i].encodeForHash(rl.buf, out) +} + +// DecodeRLP decodes a list of receipts from the network format. +func (rl *ReceiptList68) DecodeRLP(s *rlp.Stream) error { + initBuffers(&rl.buf) + if _, err := s.List(); err != nil { + return err + } + for i := 0; s.MoreDataInList(); i++ { + var item Receipt + err := item.decode68(rl.buf, s) + if err != nil { + return fmt.Errorf("receipt %d: %v", i, err) + } + rl.items = append(rl.items, item) + } + return s.ListEnd() +} + +// EncodeRLP encodes the list into the network format of eth/68. +func (rl *ReceiptList68) EncodeRLP(_w io.Writer) error { + initBuffers(&rl.buf) + w := rlp.NewEncoderBuffer(_w) + outer := w.List() + for i := range rl.items { + rl.items[i].encodeForNetwork68(rl.buf, &w) + } + w.ListEnd(outer) + return w.Flush() +} + +// ReceiptList69 is the block receipt list as downloaded by eth/69. +// This implements types.DerivableList for validation purposes. +type ReceiptList69 struct { + buf *receiptListBuffers + items []Receipt +} + +// NewReceiptList69 creates a receipt list. +// This is slow, and exists for testing purposes. +func NewReceiptList69(trs []*types.Receipt) *ReceiptList69 { + rl := &ReceiptList69{items: make([]Receipt, len(trs))} + for i, tr := range trs { + rl.items[i] = newReceipt(tr) + } + return rl +} + +// setBuffers implements ReceiptsList. +func (rl *ReceiptList69) setBuffers(buf *receiptListBuffers) { + rl.buf = buf +} + +// EncodeForStorage encodes the receipts for storage into the database. +func (rl *ReceiptList69) EncodeForStorage() rlp.RawValue { + initBuffers(&rl.buf) + return rl.buf.encodeForStorage(rl.items) +} + +// Len implements types.DerivableList. +func (rl *ReceiptList69) Len() int { + return len(rl.items) +} + +// EncodeIndex implements types.DerivableList. +func (rl *ReceiptList69) EncodeIndex(i int, out *bytes.Buffer) { + initBuffers(&rl.buf) + rl.items[i].encodeForHash(rl.buf, out) +} + +// DecodeRLP decodes a list receipts from the network format. +func (rl *ReceiptList69) DecodeRLP(s *rlp.Stream) error { + if _, err := s.List(); err != nil { + return err + } + for i := 0; s.MoreDataInList(); i++ { + var item Receipt + err := item.decode69(s) + if err != nil { + return fmt.Errorf("receipt %d: %v", i, err) + } + rl.items = append(rl.items, item) + } + return s.ListEnd() +} + +// EncodeRLP encodes the list into the network format of eth/69. +func (rl *ReceiptList69) EncodeRLP(_w io.Writer) error { + w := rlp.NewEncoderBuffer(_w) + outer := w.List() + for i := range rl.items { + rl.items[i].encodeForNetwork69(&w) + } + w.ListEnd(outer) + return w.Flush() +} + +// blockReceiptsToNetwork69 takes a slice of rlp-encoded receipts, and transactions, +// and applies the type-encoding on the receipts (for non-legacy receipts). +// e.g. for non-legacy receipts: receipt-data -> {tx-type || receipt-data} +func blockReceiptsToNetwork69(blockReceipts, blockBody rlp.RawValue) ([]byte, error) { + txTypesIter, err := txTypesInBody(blockBody) + if err != nil { + return nil, fmt.Errorf("invalid block body: %v", err) + } + nextTxType, stopTxTypes := iter.Pull(txTypesIter) + defer stopTxTypes() + + var ( + out bytes.Buffer + enc = rlp.NewEncoderBuffer(&out) + it, _ = rlp.NewListIterator(blockReceipts) + ) + outer := enc.List() + for i := 0; it.Next(); i++ { + txType, _ := nextTxType() + content, _, _ := rlp.SplitList(it.Value()) + receiptList := enc.List() + enc.WriteUint64(uint64(txType)) + enc.Write(content) + enc.ListEnd(receiptList) + } + enc.ListEnd(outer) + enc.Flush() + return out.Bytes(), nil +} + +// txTypesInBody parses the transactions list of an encoded block body, returning just the types. +func txTypesInBody(body rlp.RawValue) (iter.Seq[byte], error) { + bodyFields, _, err := rlp.SplitList(body) + if err != nil { + return nil, err + } + txsIter, err := rlp.NewListIterator(bodyFields) + if err != nil { + return nil, err + } + return func(yield func(byte) bool) { + for txsIter.Next() { + var txType byte + switch k, content, _, _ := rlp.Split(txsIter.Value()); k { + case rlp.List: + txType = 0 + case rlp.String: + if len(content) > 0 { + txType = content[0] + } + } + if !yield(txType) { + return + } + } + }, nil +} diff --git a/eth/protocols/eth/receipt_test.go b/eth/protocols/eth/receipt_test.go new file mode 100644 index 0000000000..3c73c07396 --- /dev/null +++ b/eth/protocols/eth/receipt_test.go @@ -0,0 +1,158 @@ +// Copyright 2024 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 . + +package eth + +import ( + "bytes" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +// miniDeriveFields derives the necessary receipt fields to make types.DeriveSha work. +func miniDeriveFields(r *types.Receipt, txType byte) { + r.Type = txType + r.Bloom = types.CreateBloom(r) +} + +var receiptsTestLogs1 = []*types.Log{{Address: common.Address{1}, Topics: []common.Hash{{1}}}} +var receiptsTestLogs2 = []*types.Log{ + {Address: common.Address{2}, Topics: []common.Hash{{21}, {22}}, Data: []byte{2, 2, 32, 32}}, + {Address: common.Address{3}, Topics: []common.Hash{{31}, {32}}, Data: []byte{3, 3, 32, 32}}, +} + +var receiptsTests = []struct { + input []types.ReceiptForStorage + txs []*types.Transaction + root common.Hash +}{ + { + input: []types.ReceiptForStorage{{CumulativeGasUsed: 555, Status: 1, Logs: nil}}, + txs: []*types.Transaction{types.NewTx(&types.LegacyTx{})}, + }, + { + input: []types.ReceiptForStorage{{CumulativeGasUsed: 555, Status: 1, Logs: nil}}, + txs: []*types.Transaction{types.NewTx(&types.DynamicFeeTx{})}, + }, + { + input: []types.ReceiptForStorage{{CumulativeGasUsed: 555, Status: 1, Logs: nil}}, + txs: []*types.Transaction{types.NewTx(&types.AccessListTx{})}, + }, + { + input: []types.ReceiptForStorage{{CumulativeGasUsed: 555, Status: 1, Logs: receiptsTestLogs1}}, + txs: []*types.Transaction{types.NewTx(&types.LegacyTx{})}, + }, + { + input: []types.ReceiptForStorage{{CumulativeGasUsed: 555, Status: 1, Logs: receiptsTestLogs2}}, + txs: []*types.Transaction{types.NewTx(&types.AccessListTx{})}, + }, +} + +func init() { + for i := range receiptsTests { + // derive basic fields + for j := range receiptsTests[i].input { + r := (*types.Receipt)(&receiptsTests[i].input[j]) + txType := receiptsTests[i].txs[j].Type() + miniDeriveFields(r, txType) + } + // compute expected root + receipts := make(types.Receipts, len(receiptsTests[i].input)) + for j, sr := range receiptsTests[i].input { + r := types.Receipt(sr) + receipts[j] = &r + } + receiptsTests[i].root = types.DeriveSha(receipts, trie.NewStackTrie(nil)) + } +} + +func TestReceiptList69(t *testing.T) { + for i, test := range receiptsTests { + // encode receipts from types.ReceiptForStorage object. + canonDB, _ := rlp.EncodeToBytes(test.input) + + // encode block body from types object. + blockBody := types.Body{Transactions: test.txs} + canonBody, _ := rlp.EncodeToBytes(blockBody) + + // convert from storage encoding to network encoding + network, err := blockReceiptsToNetwork69(canonDB, canonBody) + if err != nil { + t.Fatalf("test[%d]: blockReceiptsToNetwork69 error: %v", i, err) + } + + // parse as Receipts response list from network encoding + var rl ReceiptList69 + if err := rlp.DecodeBytes(network, &rl); err != nil { + t.Fatalf("test[%d]: can't decode network receipts: %v", i, err) + } + rlStorageEnc := rl.EncodeForStorage() + if !bytes.Equal(rlStorageEnc, canonDB) { + t.Fatalf("test[%d]: re-encoded receipts not equal\nhave: %x\nwant: %x", i, rlStorageEnc, canonDB) + } + rlNetworkEnc, _ := rlp.EncodeToBytes(&rl) + if !bytes.Equal(rlNetworkEnc, network) { + t.Fatalf("test[%d]: re-encoded network receipt list not equal\nhave: %x\nwant: %x", i, rlNetworkEnc, network) + } + + // compute root hash from ReceiptList69 and compare. + responseHash := types.DeriveSha(&rl, trie.NewStackTrie(nil)) + if responseHash != test.root { + t.Fatalf("test[%d]: wrong root hash from ReceiptList69\nhave: %v\nwant: %v", i, responseHash, test.root) + } + } +} + +func TestReceiptList68(t *testing.T) { + for i, test := range receiptsTests { + // encode receipts from types.ReceiptForStorage object. + canonDB, _ := rlp.EncodeToBytes(test.input) + + // encode block body from types object. + blockBody := types.Body{Transactions: test.txs} + canonBody, _ := rlp.EncodeToBytes(blockBody) + + // convert from storage encoding to network encoding + network, err := blockReceiptsToNetwork68(canonDB, canonBody) + if err != nil { + t.Fatalf("test[%d]: blockReceiptsToNetwork68 error: %v", i, err) + } + + // parse as Receipts response list from network encoding + var rl ReceiptList68 + if err := rlp.DecodeBytes(network, &rl); err != nil { + t.Fatalf("test[%d]: can't decode network receipts: %v", i, err) + } + rlStorageEnc := rl.EncodeForStorage() + if !bytes.Equal(rlStorageEnc, canonDB) { + t.Fatalf("test[%d]: re-encoded receipts not equal\nhave: %x\nwant: %x", i, rlStorageEnc, canonDB) + } + rlNetworkEnc, _ := rlp.EncodeToBytes(&rl) + if !bytes.Equal(rlNetworkEnc, network) { + t.Fatalf("test[%d]: re-encoded network receipt list not equal\nhave: %x\nwant: %x", i, rlNetworkEnc, network) + } + + // compute root hash from ReceiptList68 and compare. + responseHash := types.DeriveSha(&rl, trie.NewStackTrie(nil)) + if responseHash != test.root { + t.Fatalf("test[%d]: wrong root hash from ReceiptList68\nhave: %v\nwant: %v", i, responseHash, test.root) + } + } +} diff --git a/eth/protocols/eth/tracker.go b/eth/protocols/eth/tracker.go deleted file mode 100644 index 324fd22839..0000000000 --- a/eth/protocols/eth/tracker.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2021 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 . - -package eth - -import ( - "time" - - "github.com/ethereum/go-ethereum/p2p/tracker" -) - -// requestTracker is a singleton tracker for eth/66 and newer request times. -var requestTracker = tracker.New(ProtocolName, 5*time.Minute) From c8be0f9a74fdabe5f82fa5b647e9973c9c3567ef Mon Sep 17 00:00:00 2001 From: maskpp Date: Sat, 17 May 2025 01:35:17 +0800 Subject: [PATCH 031/365] eth: use headers in debug.GetModifiedAccountsBy* (#31765) Small optimization in debug_getModifiedAccountsBy* to avoid fetching block body. --- eth/api_debug.go | 50 +++++++++---------- eth/api_debug_test.go | 112 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 25 deletions(-) diff --git a/eth/api_debug.go b/eth/api_debug.go index d5e4dda140..188dee11aa 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -271,26 +271,26 @@ func storageRangeAt(statedb *state.StateDB, root common.Hash, address common.Add // // With one parameter, returns the list of accounts modified in the specified block. func (api *DebugAPI) GetModifiedAccountsByNumber(startNum uint64, endNum *uint64) ([]common.Address, error) { - var startBlock, endBlock *types.Block + var startHeader, endHeader *types.Header - startBlock = api.eth.blockchain.GetBlockByNumber(startNum) - if startBlock == nil { + startHeader = api.eth.blockchain.GetHeaderByNumber(startNum) + if startHeader == nil { return nil, fmt.Errorf("start block %x not found", startNum) } if endNum == nil { - endBlock = startBlock - startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash()) - if startBlock == nil { - return nil, fmt.Errorf("block %x has no parent", endBlock.Number()) + endHeader = startHeader + startHeader = api.eth.blockchain.GetHeaderByHash(startHeader.ParentHash) + if startHeader == nil { + return nil, fmt.Errorf("block %x has no parent", endHeader.Number) } } else { - endBlock = api.eth.blockchain.GetBlockByNumber(*endNum) - if endBlock == nil { + endHeader = api.eth.blockchain.GetHeaderByNumber(*endNum) + if endHeader == nil { return nil, fmt.Errorf("end block %d not found", *endNum) } } - return api.getModifiedAccounts(startBlock, endBlock) + return api.getModifiedAccounts(startHeader, endHeader) } // GetModifiedAccountsByHash returns all accounts that have changed between the @@ -299,38 +299,38 @@ func (api *DebugAPI) GetModifiedAccountsByNumber(startNum uint64, endNum *uint64 // // With one parameter, returns the list of accounts modified in the specified block. func (api *DebugAPI) GetModifiedAccountsByHash(startHash common.Hash, endHash *common.Hash) ([]common.Address, error) { - var startBlock, endBlock *types.Block - startBlock = api.eth.blockchain.GetBlockByHash(startHash) - if startBlock == nil { + var startHeader, endHeader *types.Header + startHeader = api.eth.blockchain.GetHeaderByHash(startHash) + if startHeader == nil { return nil, fmt.Errorf("start block %x not found", startHash) } if endHash == nil { - endBlock = startBlock - startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash()) - if startBlock == nil { - return nil, fmt.Errorf("block %x has no parent", endBlock.Number()) + endHeader = startHeader + startHeader = api.eth.blockchain.GetHeaderByHash(startHeader.ParentHash) + if startHeader == nil { + return nil, fmt.Errorf("block %x has no parent", endHeader.Number) } } else { - endBlock = api.eth.blockchain.GetBlockByHash(*endHash) - if endBlock == nil { + endHeader = api.eth.blockchain.GetHeaderByHash(*endHash) + if endHeader == nil { return nil, fmt.Errorf("end block %x not found", *endHash) } } - return api.getModifiedAccounts(startBlock, endBlock) + return api.getModifiedAccounts(startHeader, endHeader) } -func (api *DebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]common.Address, error) { - if startBlock.Number().Uint64() >= endBlock.Number().Uint64() { - return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startBlock.Number().Uint64(), endBlock.Number().Uint64()) +func (api *DebugAPI) getModifiedAccounts(startHeader, endHeader *types.Header) ([]common.Address, error) { + if startHeader.Number.Uint64() >= endHeader.Number.Uint64() { + return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startHeader.Number.Uint64(), endHeader.Number.Uint64()) } triedb := api.eth.BlockChain().TrieDB() - oldTrie, err := trie.NewStateTrie(trie.StateTrieID(startBlock.Root()), triedb) + oldTrie, err := trie.NewStateTrie(trie.StateTrieID(startHeader.Root), triedb) if err != nil { return nil, err } - newTrie, err := trie.NewStateTrie(trie.StateTrieID(endBlock.Root()), triedb) + newTrie, err := trie.NewStateTrie(trie.StateTrieID(endHeader.Root), triedb) if err != nil { return nil, err } diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go index 02b85f69fd..90fd22498a 100644 --- a/eth/api_debug_test.go +++ b/eth/api_debug_test.go @@ -18,25 +18,74 @@ package eth import ( "bytes" + "crypto/ecdsa" "fmt" + "math/big" "reflect" "slices" "strings" "testing" + "time" "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/triedb" "github.com/holiman/uint256" + "github.com/stretchr/testify/assert" ) var dumper = spew.ConfigState{Indent: " "} +type Account struct { + key *ecdsa.PrivateKey + addr common.Address +} + +func newAccounts(n int) (accounts []Account) { + for i := 0; i < n; i++ { + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + accounts = append(accounts, Account{key: key, addr: addr}) + } + slices.SortFunc(accounts, func(a, b Account) int { return a.addr.Cmp(b.addr) }) + return accounts +} + +// newTestBlockChain creates a new test blockchain. OBS: After test is done, teardown must be +// invoked in order to release associated resources. +func newTestBlockChain(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *core.BlockChain { + engine := ethash.NewFaker() + // Generate blocks for testing + _, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator) + + // Import the canonical chain + cacheConfig := &core.CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + SnapshotLimit: 0, + Preimages: true, + TrieDirtyDisabled: true, // Archive mode + } + chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConfig, gspec, nil, engine, vm.Config{}, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } + if n, err := chain.InsertChain(blocks); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", n, err) + } + return chain +} + func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.Dump { result := statedb.RawDump(&state.DumpConfig{ SkipCode: true, @@ -224,3 +273,66 @@ func TestStorageRangeAt(t *testing.T) { } } } + +func TestGetModifiedAccounts(t *testing.T) { + t.Parallel() + + // Initialize test accounts + accounts := newAccounts(4) + genesis := &core.Genesis{ + Config: params.TestChainConfig, + Alloc: types.GenesisAlloc{ + accounts[0].addr: {Balance: big.NewInt(params.Ether)}, + accounts[1].addr: {Balance: big.NewInt(params.Ether)}, + accounts[2].addr: {Balance: big.NewInt(params.Ether)}, + accounts[3].addr: {Balance: big.NewInt(params.Ether)}, + }, + } + genBlocks := 1 + signer := types.HomesteadSigner{} + blockChain := newTestBlockChain(t, genBlocks, genesis, func(_ int, b *core.BlockGen) { + // Transfer from account[0] to account[1] + // value: 1000 wei + // fee: 0 wei + for _, account := range accounts[:3] { + tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ + Nonce: 0, + To: &accounts[3].addr, + Value: big.NewInt(1000), + Gas: params.TxGas, + GasPrice: b.BaseFee(), + Data: nil}), + signer, account.key) + b.AddTx(tx) + } + }) + defer blockChain.Stop() + + // Create a debug API instance. + api := NewDebugAPI(&Ethereum{blockchain: blockChain}) + + // Test GetModifiedAccountsByNumber + t.Run("GetModifiedAccountsByNumber", func(t *testing.T) { + addrs, err := api.GetModifiedAccountsByNumber(uint64(genBlocks), nil) + assert.NoError(t, err) + assert.Len(t, addrs, len(accounts)+1) // +1 for the coinbase + for _, account := range accounts { + if !slices.Contains(addrs, account.addr) { + t.Fatalf("account %s not found in modified accounts", account.addr.Hex()) + } + } + }) + + // Test GetModifiedAccountsByHash + t.Run("GetModifiedAccountsByHash", func(t *testing.T) { + header := blockChain.GetHeaderByNumber(uint64(genBlocks)) + addrs, err := api.GetModifiedAccountsByHash(header.Hash(), nil) + assert.NoError(t, err) + assert.Len(t, addrs, len(accounts)+1) // +1 for the coinbase + for _, account := range accounts { + if !slices.Contains(addrs, account.addr) { + t.Fatalf("account %s not found in modified accounts", account.addr.Hex()) + } + } + }) +} From 85ae3e16f1a3456c158ba0109dad07502c4046e9 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Sun, 18 May 2025 10:25:16 +0200 Subject: [PATCH 032/365] cmd/devp2p/internal/ethtest: tests for BlockRangeUpdate (#31843) I added a test for BlockRangeUpdate in #29158 but forgot to enable it. Here I'm adding two more tests for it. Also applied a small refactoring to combine calls to `dial()` and `peer()` into a single function, since these two calls are duplicated in each test. --- cmd/devp2p/internal/ethtest/conn.go | 12 ++ cmd/devp2p/internal/ethtest/suite.go | 158 +++++++++++++++++---------- 2 files changed, 110 insertions(+), 60 deletions(-) diff --git a/cmd/devp2p/internal/ethtest/conn.go b/cmd/devp2p/internal/ethtest/conn.go index 6d8e0f1f7e..4a7a2c76d8 100644 --- a/cmd/devp2p/internal/ethtest/conn.go +++ b/cmd/devp2p/internal/ethtest/conn.go @@ -228,6 +228,18 @@ func (c *Conn) ReadSnap() (any, error) { } } +// dialAndPeer creates a peer connection and runs the handshake. +func (s *Suite) dialAndPeer(status *eth.StatusPacket69) (*Conn, error) { + c, err := s.dial() + if err != nil { + return nil, err + } + if err = c.peer(s.chain, status); err != nil { + c.Close() + } + return c, err +} + // peer performs both the protocol handshake and the status message // exchange with the node in order to peer with it. func (c *Conn) peer(chain *Chain, status *eth.StatusPacket69) error { diff --git a/cmd/devp2p/internal/ethtest/suite.go b/cmd/devp2p/internal/ethtest/suite.go index b90ecf3ca3..97e8fd84fa 100644 --- a/cmd/devp2p/internal/ethtest/suite.go +++ b/cmd/devp2p/internal/ethtest/suite.go @@ -68,6 +68,10 @@ func (s *Suite) EthTests() []utesting.Test { return []utesting.Test{ // status {Name: "Status", Fn: s.TestStatus}, + {Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake}, + {Name: "BlockRangeUpdateExpired", Fn: s.TestBlockRangeUpdateHistoryExp}, + {Name: "BlockRangeUpdateFuture", Fn: s.TestBlockRangeUpdateFuture}, + {Name: "BlockRangeUpdateInvalid", Fn: s.TestBlockRangeUpdateInvalid}, // get block headers {Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders}, {Name: "GetNonexistentBlockHeaders", Fn: s.TestGetNonexistentBlockHeaders}, @@ -77,8 +81,6 @@ func (s *Suite) EthTests() []utesting.Test { // get history {Name: "GetBlockBodies", Fn: s.TestGetBlockBodies}, {Name: "GetReceipts", Fn: s.TestGetReceipts}, - // // malicious handshakes + status - {Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake}, // test transactions {Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true}, {Name: "Transaction", Fn: s.TestTransaction}, @@ -102,15 +104,11 @@ func (s *Suite) SnapTests() []utesting.Test { func (s *Suite) TestStatus(t *utesting.T) { t.Log(`This test is just a sanity check. It performs an eth protocol handshake.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) + t.Fatal("peering failed:", err) } + conn.Close() } // headersMatch returns whether the received headers match the given request @@ -120,15 +118,12 @@ func headersMatch(expected []*types.Header, headers []*types.Header) bool { func (s *Suite) TestGetBlockHeaders(t *utesting.T) { t.Log(`This test requests block headers from the node.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } + defer conn.Close() + // Send headers request. req := ð.GetBlockHeadersPacket{ RequestId: 33, @@ -161,18 +156,13 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) { } func (s *Suite) TestGetNonexistentBlockHeaders(t *utesting.T) { - t.Log(`This test sends GetBlockHeaders requests for nonexistent blocks (using max uint64 value) + t.Log(`This test sends GetBlockHeaders requests for nonexistent blocks (using max uint64 value) to check if the node disconnects after receiving multiple invalid requests.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - - if err := conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } + defer conn.Close() // Create request with max uint64 value for a nonexistent block badReq := ð.GetBlockHeadersPacket{ @@ -205,15 +195,11 @@ to check if the node disconnects after receiving multiple invalid requests.`) func (s *Suite) TestSimultaneousRequests(t *utesting.T) { t.Log(`This test requests blocks headers from the node, performing two requests concurrently, with different request IDs.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } + defer conn.Close() // Create two different requests. req1 := ð.GetBlockHeadersPacket{ @@ -279,15 +265,11 @@ concurrently, with different request IDs.`) func (s *Suite) TestSameRequestID(t *utesting.T) { t.Log(`This test requests block headers, performing two concurrent requests with the same request ID. The node should handle the request by responding to both requests.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } + defer conn.Close() // Create two different requests with the same ID. reqID := uint64(1234) @@ -350,15 +332,12 @@ same request ID. The node should handle the request by responding to both reques func (s *Suite) TestZeroRequestID(t *utesting.T) { t.Log(`This test sends a GetBlockHeaders message with a request-id of zero, and expects a response.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } + defer conn.Close() + req := ð.GetBlockHeadersPacket{ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{Number: 0}, @@ -385,15 +364,12 @@ and expects a response.`) func (s *Suite) TestGetBlockBodies(t *utesting.T) { t.Log(`This test sends GetBlockBodies requests to the node for known blocks in the test chain.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } + defer conn.Close() + // Create block bodies request. req := ð.GetBlockBodiesPacket{ RequestId: 55, @@ -421,15 +397,11 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) { func (s *Suite) TestGetReceipts(t *utesting.T) { t.Log(`This test sends GetReceipts requests to the node for known blocks in the test chain.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } + defer conn.Close() // Find some blocks containing receipts. var hashes = make([]common.Hash, 0, 3) @@ -546,17 +518,13 @@ func (s *Suite) TestMaliciousHandshake(t *utesting.T) { } } -func (s *Suite) TestInvalidBlockRangeUpdate(t *utesting.T) { +func (s *Suite) TestBlockRangeUpdateInvalid(t *utesting.T) { t.Log(`This test sends an invalid BlockRangeUpdate message to the node and expects to be disconnected.`) - - conn, err := s.dial() + conn, err := s.dialAndPeer(nil) if err != nil { - t.Fatalf("dial failed: %v", err) + t.Fatal(err) } defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } conn.Write(ethProto, eth.BlockRangeUpdateMsg, ð.BlockRangeUpdatePacket{ EarliestBlock: 10, @@ -571,6 +539,76 @@ func (s *Suite) TestInvalidBlockRangeUpdate(t *utesting.T) { } } +func (s *Suite) TestBlockRangeUpdateFuture(t *utesting.T) { + t.Log(`This test sends a BlockRangeUpdate that is beyond the chain head. +The node should accept the update and should not disonnect.`) + conn, err := s.dialAndPeer(nil) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + head := s.chain.Head().NumberU64() + var hash common.Hash + rand.Read(hash[:]) + conn.Write(ethProto, eth.BlockRangeUpdateMsg, ð.BlockRangeUpdatePacket{ + EarliestBlock: head + 10, + LatestBlock: head + 50, + LatestBlockHash: hash, + }) + + // Ensure the node does not disconnect us. + // Just send a few ping messages. + for range 10 { + time.Sleep(100 * time.Millisecond) + if err := conn.Write(baseProto, pingMsg, []any{}); err != nil { + t.Fatal("write error:", err) + } + code, _, err := conn.Read() + switch { + case err != nil: + t.Fatal("read error:", err) + case code == discMsg: + t.Fatal("got disconnect") + case code == pongMsg: + } + } +} + +func (s *Suite) TestBlockRangeUpdateHistoryExp(t *utesting.T) { + t.Log(`This test sends a BlockRangeUpdate announcing incomplete (expired) history. +The node should accept the update and should not disonnect.`) + conn, err := s.dialAndPeer(nil) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + head := s.chain.Head() + conn.Write(ethProto, eth.BlockRangeUpdateMsg, ð.BlockRangeUpdatePacket{ + EarliestBlock: head.NumberU64() - 10, + LatestBlock: head.NumberU64(), + LatestBlockHash: head.Hash(), + }) + + // Ensure the node does not disconnect us. + // Just send a few ping messages. + for range 10 { + time.Sleep(100 * time.Millisecond) + if err := conn.Write(baseProto, pingMsg, []any{}); err != nil { + t.Fatal("write error:", err) + } + code, _, err := conn.Read() + switch { + case err != nil: + t.Fatal("read error:", err) + case code == discMsg: + t.Fatal("got disconnect") + case code == pongMsg: + } + } +} + func (s *Suite) TestTransaction(t *utesting.T) { t.Log(`This test sends a valid transaction to the node and checks if the transaction gets propagated.`) From 15057e7f7fbcb6b22f2f0a7e740b65db2959b78b Mon Sep 17 00:00:00 2001 From: Zhou Date: Mon, 19 May 2025 03:59:35 +0200 Subject: [PATCH 033/365] core: don't emit the warning of log indexing if the db was not initialized (#31845) --- core/filtermaps/filtermaps.go | 2 +- core/rawdb/accessors_indexes.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/filtermaps/filtermaps.go b/core/filtermaps/filtermaps.go index b2c63f2e58..667d7c7623 100644 --- a/core/filtermaps/filtermaps.go +++ b/core/filtermaps/filtermaps.go @@ -227,7 +227,7 @@ type Config struct { // NewFilterMaps creates a new FilterMaps and starts the indexer. func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, finalBlock uint64, params Params, config Config) *FilterMaps { rs, initialized, err := rawdb.ReadFilterMapsRange(db) - if err != nil || rs.Version != databaseVersion { + if err != nil || (initialized && rs.Version != databaseVersion) { rs, initialized = rawdb.FilterMapsRange{}, false log.Warn("Invalid log index database version; resetting log index") } diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index 1a5c414c8e..fafde25606 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -446,7 +446,7 @@ type FilterMapsRange struct { // database entry is not present, that is interpreted as a valid non-initialized // state and returns a blank range structure and no error. func ReadFilterMapsRange(db ethdb.KeyValueReader) (FilterMapsRange, bool, error) { - if has, err := db.Has(filterMapsRangeKey); !has || err != nil { + if has, err := db.Has(filterMapsRangeKey); err != nil || !has { return FilterMapsRange{}, false, err } encRange, err := db.Get(filterMapsRangeKey) @@ -457,7 +457,8 @@ func ReadFilterMapsRange(db ethdb.KeyValueReader) (FilterMapsRange, bool, error) if err := rlp.DecodeBytes(encRange, &fmRange); err != nil { return FilterMapsRange{}, false, err } - return fmRange, true, err + + return fmRange, true, nil } // WriteFilterMapsRange stores the filter maps range data. From 0867c24662f5c954c60b7ebdb3e32fc44e9a1bb4 Mon Sep 17 00:00:00 2001 From: maskpp Date: Mon, 19 May 2025 10:03:59 +0800 Subject: [PATCH 034/365] trie: use common.Hash as the key in secKeyCache map (#31786) --- trie/secure_trie.go | 60 +++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/trie/secure_trie.go b/trie/secure_trie.go index 45d5fd63e7..7852e16619 100644 --- a/trie/secure_trie.go +++ b/trie/secure_trie.go @@ -19,6 +19,7 @@ package trie import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/triedb/database" @@ -63,8 +64,7 @@ type StateTrie struct { trie Trie db database.NodeDatabase preimages preimageStore - hashKeyBuf [common.HashLength]byte - secKeyCache map[string][]byte + secKeyCache map[common.Hash][]byte secKeyCacheOwner *StateTrie // Pointer to self, replace the key cache on mismatch } @@ -97,7 +97,7 @@ func NewStateTrie(id *ID, db database.NodeDatabase) (*StateTrie, error) { // This function will omit any encountered error but just // print out an error message. func (t *StateTrie) MustGet(key []byte) []byte { - return t.trie.MustGet(t.hashKey(key)) + return t.trie.MustGet(crypto.Keccak256(key)) } // GetStorage attempts to retrieve a storage slot with provided account address @@ -105,7 +105,7 @@ func (t *StateTrie) MustGet(key []byte) []byte { // If the specified storage slot is not in the trie, nil will be returned. // If a trie node is not found in the database, a MissingNodeError is returned. func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) { - enc, err := t.trie.Get(t.hashKey(key)) + enc, err := t.trie.Get(crypto.Keccak256(key)) if err != nil || len(enc) == 0 { return nil, err } @@ -117,7 +117,7 @@ func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) { // If the specified account is not in the trie, nil will be returned. // If a trie node is not found in the database, a MissingNodeError is returned. func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) { - res, err := t.trie.Get(t.hashKey(address.Bytes())) + res, err := t.trie.Get(crypto.Keccak256(address.Bytes())) if res == nil || err != nil { return nil, err } @@ -157,9 +157,9 @@ func (t *StateTrie) GetNode(path []byte) ([]byte, int, error) { // This function will omit any encountered error but just print out an // error message. func (t *StateTrie) MustUpdate(key, value []byte) { - hk := t.hashKey(key) + hk := crypto.Keccak256(key) t.trie.MustUpdate(hk, value) - t.getSecKeyCache()[string(hk)] = common.CopyBytes(key) + t.getSecKeyCache()[common.Hash(hk)] = common.CopyBytes(key) } // UpdateStorage associates key with value in the trie. Subsequent calls to @@ -171,19 +171,19 @@ func (t *StateTrie) MustUpdate(key, value []byte) { // // If a node is not found in the database, a MissingNodeError is returned. func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error { - hk := t.hashKey(key) + hk := crypto.Keccak256(key) v, _ := rlp.EncodeToBytes(value) err := t.trie.Update(hk, v) if err != nil { return err } - t.getSecKeyCache()[string(hk)] = common.CopyBytes(key) + t.getSecKeyCache()[common.Hash(hk)] = common.CopyBytes(key) return nil } // UpdateAccount will abstract the write of an account to the secure trie. func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount, _ int) error { - hk := t.hashKey(address.Bytes()) + hk := crypto.Keccak256(address.Bytes()) data, err := rlp.EncodeToBytes(acc) if err != nil { return err @@ -191,7 +191,7 @@ func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccoun if err := t.trie.Update(hk, data); err != nil { return err } - t.getSecKeyCache()[string(hk)] = address.Bytes() + t.getSecKeyCache()[common.Hash(hk)] = address.Bytes() return nil } @@ -202,8 +202,8 @@ func (t *StateTrie) UpdateContractCode(_ common.Address, _ common.Hash, _ []byte // MustDelete removes any existing value for key from the trie. This function // will omit any encountered error but just print out an error message. func (t *StateTrie) MustDelete(key []byte) { - hk := t.hashKey(key) - delete(t.getSecKeyCache(), string(hk)) + hk := crypto.Keccak256(key) + delete(t.getSecKeyCache(), common.Hash(hk)) t.trie.MustDelete(hk) } @@ -211,22 +211,22 @@ func (t *StateTrie) MustDelete(key []byte) { // If the specified trie node is not in the trie, nothing will be changed. // If a node is not found in the database, a MissingNodeError is returned. func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error { - hk := t.hashKey(key) - delete(t.getSecKeyCache(), string(hk)) + hk := crypto.Keccak256(key) + delete(t.getSecKeyCache(), common.Hash(hk)) return t.trie.Delete(hk) } // DeleteAccount abstracts an account deletion from the trie. func (t *StateTrie) DeleteAccount(address common.Address) error { - hk := t.hashKey(address.Bytes()) - delete(t.getSecKeyCache(), string(hk)) + hk := crypto.Keccak256(address.Bytes()) + delete(t.getSecKeyCache(), common.Hash(hk)) return t.trie.Delete(hk) } // GetKey returns the sha3 preimage of a hashed key that was // previously used to store a value. func (t *StateTrie) GetKey(shaKey []byte) []byte { - if key, ok := t.getSecKeyCache()[string(shaKey)]; ok { + if key, ok := t.getSecKeyCache()[common.BytesToHash(shaKey)]; ok { return key } if t.preimages == nil { @@ -251,13 +251,9 @@ func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) { // Write all the pre-images to the actual disk database if len(t.getSecKeyCache()) > 0 { if t.preimages != nil { - preimages := make(map[common.Hash][]byte, len(t.secKeyCache)) - for hk, key := range t.secKeyCache { - preimages[common.BytesToHash([]byte(hk))] = key - } - t.preimages.InsertPreimage(preimages) + t.preimages.InsertPreimage(t.secKeyCache) } - t.secKeyCache = make(map[string][]byte) + t.secKeyCache = make(map[common.Hash][]byte) } // Commit the trie and return its modified nodeset. return t.trie.Commit(collectLeaf) @@ -291,25 +287,13 @@ func (t *StateTrie) MustNodeIterator(start []byte) NodeIterator { return t.trie.MustNodeIterator(start) } -// hashKey returns the hash of key as an ephemeral buffer. -// The caller must not hold onto the return value because it will become -// invalid on the next call to hashKey or secKey. -func (t *StateTrie) hashKey(key []byte) []byte { - h := newHasher(false) - h.sha.Reset() - h.sha.Write(key) - h.sha.Read(t.hashKeyBuf[:]) - returnHasherToPool(h) - return t.hashKeyBuf[:] -} - // getSecKeyCache returns the current secure key cache, creating a new one if // ownership changed (i.e. the current secure trie is a copy of another owning // the actual cache). -func (t *StateTrie) getSecKeyCache() map[string][]byte { +func (t *StateTrie) getSecKeyCache() map[common.Hash][]byte { if t != t.secKeyCacheOwner { t.secKeyCacheOwner = t - t.secKeyCache = make(map[string][]byte) + t.secKeyCache = make(map[common.Hash][]byte) } return t.secKeyCache } From e79177d1bca6bd21ed78bd8c2bf7144b36395c78 Mon Sep 17 00:00:00 2001 From: Csaba Kiraly Date: Mon, 19 May 2025 12:56:12 +0200 Subject: [PATCH 035/365] cmd/utils: remove duplicate code for influxDB tags (#31854) remove duplicate code Signed-off-by: Csaba Kiraly --- cmd/utils/flags.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 169f5ed49e..81c4172a53 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2020,7 +2020,6 @@ func SetupMetrics(cfg *metrics.Config) { log.Info("Enabling metrics export to InfluxDB") go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) } else if enableExportV2 { - tagsMap := SplitTagsFlag(cfg.InfluxDBTags) log.Info("Enabling metrics export to InfluxDB (v2)") go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap) } From 33c5031a2e6888dbac3dba0628c786442ceabc33 Mon Sep 17 00:00:00 2001 From: Zhou Date: Mon, 19 May 2025 10:55:17 -0300 Subject: [PATCH 036/365] internal: remove eth_{compile,getWork,submitWork} from console (#31856) The `compile` and `eth_getWork` `eth_submitWork` apis were not available anymore, so try to remove them --- internal/jsre/deps/web3.js | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/internal/jsre/deps/web3.js b/internal/jsre/deps/web3.js index a4141bac43..0aa738a2af 100644 --- a/internal/jsre/deps/web3.js +++ b/internal/jsre/deps/web3.js @@ -5435,36 +5435,6 @@ var methods = function () { outputFormatter: utils.toDecimal }); - var compileSolidity = new Method({ - name: 'compile.solidity', - call: 'eth_compileSolidity', - params: 1 - }); - - var compileLLL = new Method({ - name: 'compile.lll', - call: 'eth_compileLLL', - params: 1 - }); - - var compileSerpent = new Method({ - name: 'compile.serpent', - call: 'eth_compileSerpent', - params: 1 - }); - - var submitWork = new Method({ - name: 'submitWork', - call: 'eth_submitWork', - params: 3 - }); - - var getWork = new Method({ - name: 'getWork', - call: 'eth_getWork', - params: 0 - }); - return [ getBalance, getStorageAt, @@ -5483,12 +5453,7 @@ var methods = function () { sendRawTransaction, signTransaction, sendTransaction, - sign, - compileSolidity, - compileLLL, - compileSerpent, - submitWork, - getWork + sign ]; }; From a67ea0c57dd7b387fc49138f4bdc1590c91e5a51 Mon Sep 17 00:00:00 2001 From: James Niken Date: Tue, 20 May 2025 09:58:00 +0200 Subject: [PATCH 037/365] internal/reexec: fix broken link to Docker/Moby in comment (#31859) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hey team—noticed a dead link, replaced it with a working URL https://github.com/moby/moby/blob/master/pkg/reexec/reexec.go - old link https://github.com/moby/moby/blob/master/pkg/reexec/reexec_deprecated.go - new link --- internal/reexec/reexec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/reexec/reexec.go b/internal/reexec/reexec.go index 7dc6d9222e..50c0f43ab8 100644 --- a/internal/reexec/reexec.go +++ b/internal/reexec/reexec.go @@ -1,5 +1,5 @@ // This file originates from Docker/Moby, -// https://github.com/moby/moby/blob/master/pkg/reexec/reexec.go +// https://github.com/moby/moby/blob/master/pkg/reexec/reexec_deprecated.go // Licensed under Apache License 2.0: https://github.com/moby/moby/blob/master/LICENSE // Copyright 2013-2018 Docker, Inc. // From 24771fdba4fb7b414bfd5491b182ac0d22dfb33f Mon Sep 17 00:00:00 2001 From: VolodymyrBg Date: Tue, 20 May 2025 11:04:37 +0300 Subject: [PATCH 038/365] README: update broken JSON-RPC API documentation link (#31860) I've updated the broken link to point to the current official Ethereum JSON-RPC API documentation at https://ethereum.org/en/developers/docs/apis/json-rpc/. This is the correct and up-to-date location for the Ethereum Execution Layer APIs documentation. The link should now work properly. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ccfe933aa..78a56baece 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,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/) +this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.org/en/developers/docs/apis/json-rpc/) 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). From e4a8ecb9473dfbc809d3f413412df1d05a78607c Mon Sep 17 00:00:00 2001 From: steven Date: Tue, 20 May 2025 20:57:01 +0800 Subject: [PATCH 039/365] core/txpool/legacypool: fix flaky test TestAllowedTxSize #30975 (#31836) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some tests involving transactions near the txMaxSize limit were flaky. This was due to ECDSA signatures occasionally having leading zeros, which are omitted during RLP encoding — making the final transaction size 1 byte smaller than expected. To address this, a new helper function pricedDataTransactionWithFixedSignature was added. It ensures both r and s are exactly 32 bytes (i.e., no leading zeros), producing transactions with deterministic size. --- core/txpool/legacypool/legacypool_test.go | 34 +++++++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 2fdf890320..1ba080b749 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -108,11 +108,33 @@ func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ec return tx } -func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, bytes uint64) *types.Transaction { - data := make([]byte, bytes) - crand.Read(data) - - tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data), types.HomesteadSigner{}, key) +// pricedDataTransaction generates a signed transaction with fixed-size data, +// and ensures that the resulting signature components (r and s) are exactly 32 bytes each, +// producing transactions with deterministic size. +// +// This avoids variability in transaction size caused by leading zeros being omitted in +// RLP encoding of r/s. Since r and s are derived from ECDSA, they occasionally have leading +// zeros and thus can be shorter than 32 bytes. +// +// For example: +// +// r: 0 leading zeros, bytesSize: 32, bytes: [221 ... 101] +// s: 1 leading zeros, bytesSize: 31, bytes: [0 75 ... 47] +func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, dataBytes uint64) *types.Transaction { + var tx *types.Transaction + + // 10 attempts is statistically sufficient since leading zeros in ECDSA signatures are rare and randomly distributed. + var retryTimes = 10 + for i := 0; i < retryTimes; i++ { + data := make([]byte, dataBytes) + crand.Read(data) + + tx, _ = types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data), types.HomesteadSigner{}, key) + _, r, s := tx.RawSignatureValues() + if len(r.Bytes()) == 32 && len(s.Bytes()) == 32 { + break + } + } return tx } @@ -1239,7 +1261,7 @@ func TestAllowedTxSize(t *testing.T) { const largeDataLength = txMaxSize - 200 // enough to have a 5 bytes RLP encoding of the data length number txWithLargeData := pricedDataTransaction(0, pool.currentHead.Load().GasLimit, big.NewInt(1), key, largeDataLength) maxTxLengthWithoutData := txWithLargeData.Size() - largeDataLength // 103 bytes - maxTxDataLength := txMaxSize - maxTxLengthWithoutData // 131072 - 103 = 130953 bytes + maxTxDataLength := txMaxSize - maxTxLengthWithoutData // 131072 - 103 = 130969 bytes // Try adding a transaction with maximal allowed size tx := pricedDataTransaction(0, pool.currentHead.Load().GasLimit, big.NewInt(1), key, maxTxDataLength) From 62aa6b2621631f61c51e678948556750eabfc620 Mon Sep 17 00:00:00 2001 From: shahafn Date: Tue, 20 May 2025 16:38:33 +0300 Subject: [PATCH 040/365] eth/tracers/native: add erc7562 tracer (#31006) This PR introduces a new native tracer for AA bundlers. Bundlers participating in the alternative mempool will need to validate userops. This tracer will return sufficient information for them to decide whether griefing is possible. Resolves #30546 --------- Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com> --- .../internal/tracetest/erc7562_tracer_test.go | 144 +++++ .../erc7562Tracer.test_deployer.json | 110 ++++ .../erc7562Tracer.test_paymaster.json | 110 ++++ .../erc7562Tracer.test_simple.json | 246 ++++++++ eth/tracers/native/erc7562.go | 530 ++++++++++++++++++ .../native/gen_callframewithopcodes_json.go | 159 ++++++ 6 files changed, 1299 insertions(+) create mode 100644 eth/tracers/internal/tracetest/erc7562_tracer_test.go create mode 100644 eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_deployer.json create mode 100644 eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_paymaster.json create mode 100644 eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_simple.json create mode 100644 eth/tracers/native/erc7562.go create mode 100644 eth/tracers/native/gen_callframewithopcodes_json.go diff --git a/eth/tracers/internal/tracetest/erc7562_tracer_test.go b/eth/tracers/internal/tracetest/erc7562_tracer_test.go new file mode 100644 index 0000000000..f6e81f5886 --- /dev/null +++ b/eth/tracers/internal/tracetest/erc7562_tracer_test.go @@ -0,0 +1,144 @@ +// Copyright 2025 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 . + +package tracetest + +import ( + "encoding/json" + "math/big" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/tests" + "github.com/stretchr/testify/require" +) + +type accessedSlots struct { + Reads map[string][]string `json:"reads"` + Writes map[string]uint64 `json:"writes"` + TransientReads map[string]uint64 `json:"transientReads"` + TransientWrites map[string]uint64 `json:"transientWrites"` +} +type contractSizeWithOpcode struct { + ContractSize int `json:"contractSize"` + Opcode vm.OpCode `json:"opcode"` +} + +// erc7562Trace is the result of a erc7562Tracer run. +type erc7562Trace struct { + From common.Address `json:"from"` + Gas *hexutil.Uint64 `json:"gas"` + GasUsed *hexutil.Uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input hexutil.Bytes `json:"input" rlp:"optional"` + Output hexutil.Bytes `json:"output,omitempty" rlp:"optional"` + Error string `json:"error,omitempty" rlp:"optional"` + RevertReason string `json:"revertReason,omitempty"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` + AccessedSlots accessedSlots `json:"accessedSlots"` + ExtCodeAccessInfo []common.Address `json:"extCodeAccessInfo"` + UsedOpcodes map[hexutil.Uint64]uint64 `json:"usedOpcodes"` + ContractSize map[common.Address]*contractSizeWithOpcode `json:"contractSize"` + OutOfGas bool `json:"outOfGas"` + Calls []erc7562Trace `json:"calls,omitempty" rlp:"optional"` + Keccak []hexutil.Bytes `json:"keccak,omitempty"` + Type string `json:"type"` +} + +// erc7562TracerTest defines a single test to check the erc7562 tracer against. +type erc7562TracerTest struct { + tracerTestEnv + Result *erc7562Trace `json:"result"` +} + +func TestErc7562Tracer(t *testing.T) { + dirPath := "erc7562_tracer" + tracerName := "erc7562Tracer" + files, err := os.ReadDir(filepath.Join("testdata", dirPath)) + if err != nil { + t.Fatalf("failed to retrieve tracer test suite: %v", err) + } + for _, file := range files { + if !strings.HasSuffix(file.Name(), ".json") { + continue + } + t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) { + t.Parallel() + + var ( + test = new(erc7562TracerTest) + tx = new(types.Transaction) + ) + // erc7562 tracer test found, read if from disk + if blob, err := os.ReadFile(filepath.Join("testdata", dirPath, file.Name())); err != nil { + t.Fatalf("failed to read testcase: %v", err) + } else if err := json.Unmarshal(blob, test); err != nil { + t.Fatalf("failed to parse testcase: %v", err) + } + if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil { + t.Fatalf("failed to parse testcase input: %v", err) + } + // Configure a blockchain with the given prestate + var ( + signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) + context = test.Context.toBlockContext(test.Genesis) + st = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) + ) + st.Close() + + tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config) + if err != nil { + t.Fatalf("failed to create erc7562 tracer: %v", err) + } + logState := vm.StateDB(st.StateDB) + if tracer.Hooks != nil { + logState = state.NewHookedState(st.StateDB, tracer.Hooks) + } + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) + if err != nil { + t.Fatalf("failed to prepare transaction for tracing: %v", err) + } + evm := vm.NewEVM(context, logState, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) + tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) + vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) + if err != nil { + t.Fatalf("failed to execute transaction: %v", err) + } + tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil) + // Retrieve the trace result and compare against the expected. + res, err := tracer.GetResult() + if err != nil { + t.Fatalf("failed to retrieve trace result: %v", err) + } + want, err := json.Marshal(test.Result) + if err != nil { + t.Fatalf("failed to marshal test: %v", err) + } + require.JSONEq(t, string(res), string(want)) + }) + } +} diff --git a/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_deployer.json b/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_deployer.json new file mode 100644 index 0000000000..2d785a1655 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_deployer.json @@ -0,0 +1,110 @@ +{ + "genesis": { + "baseFeePerGas": "1664", + "blobGasUsed": "0", + "difficulty": "0", + "excessBlobGas": "0", + "extraData": "0xd883010e0d846765746888676f312e32322e36856c696e7578", + "gasLimit": "30000000", + "hash": "0xc567fbb11719be3bc47e77269365baef50b1fc0149f2a366a35f82ddba608b28", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x792aa153a3b49ad9eb965809fedc3b11c343da37b1edebe101401711c63eb53c", + "nonce": "0x0000000000000000", + "number": "114", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "stateRoot": "0xf18f522f27f64c34e56338820450991b6fcb7a2a311224d2bfba7afa5734888b", + "timestamp": "1738267577", + "withdrawals": [], + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "alloc": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x285013864dbff82" + }, + "0x0000000071727de22e5e9d8baf0edac6f37da032": { + "balance": "0x49c2dbeb2e8d0f042", + "code": "0x60806040526004361015610024575b361561001957600080fd5b61002233612748565b005b60003560e01c806242dc5314611b0057806301ffc9a7146119ae5780630396cb60146116765780630bd28e3b146115fa5780631b2e01b814611566578063205c2878146113d157806322cdde4c1461136b57806335567e1a146112b35780635287ce12146111a557806370a0823114611140578063765e827f14610e82578063850aaf6214610dc35780639b249f6914610c74578063b760faf914610c3a578063bb9fe6bf14610a68578063c23a5cea146107c4578063dbed18e0146101a15763fc7e286d0361000e573461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61013a61229f565b16600052600060205260a0604060002065ffffffffffff6001825492015460405192835260ff8116151560208401526dffffffffffffffffffffffffffff8160081c16604084015263ffffffff8160781c16606084015260981c166080820152f35b600080fd5b3461019c576101af36612317565b906101b86129bd565b60009160005b82811061056f57506101d08493612588565b6000805b8481106102fc5750507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000809360005b81811061024757610240868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2613ba7565b6001600255005b6102a261025582848a612796565b73ffffffffffffffffffffffffffffffffffffffff6102766020830161282a565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a2806127d6565b906000915b8083106102b957505050600101610209565b909194976102f36102ed6001926102e78c8b6102e0826102da8e8b8d61269d565b9261265a565b5191613597565b90612409565b99612416565b950191906102a7565b6020610309828789612796565b61031f61031682806127d6565b9390920161282a565b9160009273ffffffffffffffffffffffffffffffffffffffff8091165b8285106103505750505050506001016101d4565b909192939561037f83610378610366848c61265a565b516103728b898b61269d565b856129f6565b9290613dd7565b9116840361050a576104a5576103958491613dd7565b9116610440576103b5576103aa600191612416565b96019392919061033c565b60a487604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b61057a818487612796565b9361058585806127d6565b919095602073ffffffffffffffffffffffffffffffffffffffff6105aa82840161282a565b1697600192838a1461076657896105da575b5050505060019293949550906105d191612409565b939291016101be565b8060406105e892019061284b565b918a3b1561019c57929391906040519485937f2dd8113300000000000000000000000000000000000000000000000000000000855288604486016040600488015252606490818601918a60051b8701019680936000915b8c83106106e657505050505050838392610684927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8560009803016024860152612709565b03818a5afa90816106d7575b506106c657602486604051907f86a9f7500000000000000000000000000000000000000000000000000000000082526004820152fd5b93945084936105d1600189806105bc565b6106e0906121bd565b88610690565b91939596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c908a9294969a0301865288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181121561019c57836107538793858394016128ec565b9a0196019301909189979695949261063f565b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b3461019c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576107fc61229f565b33600052600082526001604060002001908154916dffffffffffffffffffffffffffff8360081c16928315610a0a5765ffffffffffff8160981c1680156109ac57421061094e5760009373ffffffffffffffffffffffffffffffffffffffff859485947fffffffffffffff000000000000000000000000000000000000000000000000ff86951690556040517fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda33391806108da8786836020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0390a2165af16108e8612450565b50156108f057005b606490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b3461019c5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c573360005260006020526001604060002001805463ffffffff8160781c16908115610bdc5760ff1615610b7e5765ffffffffffff908142160191818311610b4f5780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609885901b161790556040519116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a2005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610022610c6f61229f565b612748565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043567ffffffffffffffff811161019c576020610cc8610d1b9236906004016122c2565b919073ffffffffffffffffffffffffffffffffffffffff9260405194859283927f570e1a360000000000000000000000000000000000000000000000000000000084528560048501526024840191612709565b03816000857f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c165af1908115610db757602492600092610d86575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b610da991925060203d602011610db0575b610da181836121ed565b8101906126dd565b9083610d56565b503d610d97565b6040513d6000823e3d90fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610dfa61229f565b60243567ffffffffffffffff811161019c57600091610e1e839236906004016122c2565b90816040519283928337810184815203915af4610e39612450565b90610e7e6040519283927f99410554000000000000000000000000000000000000000000000000000000008452151560048401526040602484015260448301906123c6565b0390fd5b3461019c57610e9036612317565b610e9b9291926129bd565b610ea483612588565b60005b848110610f1c57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000915b858310610eec576102408585613ba7565b909193600190610f12610f0087898761269d565b610f0a888661265a565b519088613597565b0194019190610edb565b610f47610f40610f2e8385979561265a565b51610f3a84898761269d565b846129f6565b9190613dd7565b73ffffffffffffffffffffffffffffffffffffffff929183166110db5761107657610f7190613dd7565b911661101157610f8657600101929092610ea7565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61118c61229f565b1660005260006020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff6111f161229f565b6000608060405161120181612155565b828152826020820152826040820152826060820152015216600052600060205260a06040600020608060405161123681612155565b6001835493848352015490602081019060ff8316151582526dffffffffffffffffffffffffffff60408201818560081c16815263ffffffff936060840193858760781c16855265ffffffffffff978891019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760206112ec61229f565b73ffffffffffffffffffffffffffffffffffffffff6113096122f0565b911660005260018252604060002077ffffffffffffffffffffffffffffffffffffffffffffffff821660005282526040600020547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b3461019c577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60208136011261019c576004359067ffffffffffffffff821161019c5761012090823603011261019c576113c9602091600401612480565b604051908152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761140861229f565b60243590336000526000602052604060002090815491828411611508576000808573ffffffffffffffffffffffffffffffffffffffff8295839561144c848a612443565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af16114a2612450565b50156114aa57005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761159d61229f565b73ffffffffffffffffffffffffffffffffffffffff6115ba6122f0565b9116600052600160205277ffffffffffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043577ffffffffffffffffffffffffffffffffffffffffffffffff811680910361019c5733600052600160205260406000209060005260205260406000206116728154612416565b9055005b6020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043563ffffffff9182821680920361019c5733600052600081526040600020928215611950576001840154908160781c1683106118f2576116f86dffffffffffffffffffffffffffff9182349160081c16612409565b93841561189457818511611836579065ffffffffffff61180592546040519061172082612155565b8152848101926001845260408201908816815260608201878152600160808401936000855233600052600089526040600020905181550194511515917fffffffffffffffffffffffffff0000000000000000000000000000000000000060ff72ffffffff0000000000000000000000000000006effffffffffffffffffffffffffff008954945160081b16945160781b1694169116171717835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b6040519283528201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a2005b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019c57807f60fc6b6e0000000000000000000000000000000000000000000000000000000060209214908115611ad6575b8115611aac575b8115611a82575b8115611a58575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482611a4d565b7f3e84f0210000000000000000000000000000000000000000000000000000000081149150611a46565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150611a3f565b7f915074d80000000000000000000000000000000000000000000000000000000081149150611a38565b3461019c576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5767ffffffffffffffff60043581811161019c573660238201121561019c57611b62903690602481600401359101612268565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c0811261019c5761014060405191611b9e83612155565b1261019c5760405192611bb0846121a0565b60243573ffffffffffffffffffffffffffffffffffffffff8116810361019c578452602093604435858201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff8116810361019c5760e08201526101243561010082015261014435610120820152825261016435848301526101843560408301526101a43560608301526101c43560808301526101e43590811161019c57611c7c9036906004016122c2565b905a3033036120f7578351606081015195603f5a0260061c61271060a0840151890101116120ce5760009681519182611ff0575b5050505090611cca915a9003608085015101923691612268565b925a90600094845193611cdc85613ccc565b9173ffffffffffffffffffffffffffffffffffffffff60e0870151168015600014611ea957505073ffffffffffffffffffffffffffffffffffffffff855116935b5a9003019360a06060820151910151016080860151850390818111611e95575b50508302604085015192818410600014611dce5750506003811015611da157600203611d79576113c99293508093611d7481613d65565b613cf6565b5050507fdeadaa51000000000000000000000000000000000000000000000000000000008152fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b81611dde92979396940390613c98565b506003841015611e6857507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f60808683015192519473ffffffffffffffffffffffffffffffffffffffff865116948873ffffffffffffffffffffffffffffffffffffffff60e0890151169701519160405192835215898301528760408301526060820152a46113c9565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b6064919003600a0204909301928780611d3d565b8095918051611eba575b5050611d1d565b6003861015611fc1576002860315611eb35760a088015190823b1561019c57600091611f2491836040519586809581947f7c627b210000000000000000000000000000000000000000000000000000000083528d60048401526080602484015260848301906123c6565b8b8b0260448301528b60648301520393f19081611fad575b50611fa65787893d610800808211611f9e575b506040519282828501016040528184528284013e610e7e6040519283927fad7954bc000000000000000000000000000000000000000000000000000000008452600484015260248301906123c6565b905083611f4f565b8980611eb3565b611fb89199506121bd565b6000978a611f3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91600092918380938c73ffffffffffffffffffffffffffffffffffffffff885116910192f115612023575b808080611cb0565b611cca929195503d6108008082116120c6575b5060405190888183010160405280825260008983013e805161205f575b5050600194909161201b565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20188870151918973ffffffffffffffffffffffffffffffffffffffff8551169401516120bc604051928392835260408d84015260408301906123c6565b0390a38680612053565b905088612036565b877fdeaddead000000000000000000000000000000000000000000000000000000006000526000fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff82111761217157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610140810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157604052565b6060810190811067ffffffffffffffff82111761217157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926122748261222e565b9161228260405193846121ed565b82948184528183011161019c578281602093846000960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9181601f8401121561019c5782359167ffffffffffffffff831161019c576020838186019501011161019c57565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261019c5760043567ffffffffffffffff9283821161019c578060238301121561019c57816004013593841161019c5760248460051b8301011161019c57602401919060243573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b60005b8381106123b65750506000910152565b81810151838201526020016123a6565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093612402815180928187528780880191016123a3565b0116010190565b91908201809211610b4f57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610b4f5760010190565b91908203918211610b4f57565b3d1561247b573d906124618261222e565b9161246f60405193846121ed565b82523d6000602084013e565b606090565b604061248e8183018361284b565b90818351918237206124a3606084018461284b565b90818451918237209260c06124bb60e083018361284b565b908186519182372091845195602087019473ffffffffffffffffffffffffffffffffffffffff833516865260208301358789015260608801526080870152608081013560a087015260a081013582870152013560e08501526101009081850152835261012083019167ffffffffffffffff918484108385111761217157838252845190206101408501908152306101608601524661018086015260608452936101a00191821183831017612171575251902090565b67ffffffffffffffff81116121715760051b60200190565b9061259282612570565b6040906125a260405191826121ed565b8381527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06125d08295612570565b019160005b8381106125e25750505050565b60209082516125f081612155565b83516125fb816121a0565b600081526000849181838201528187820152816060818184015260809282848201528260a08201528260c08201528260e082015282610100820152826101208201528652818587015281898701528501528301528286010152016125d5565b805182101561266e5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919081101561266e5760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18136030182121561019c570190565b9081602091031261019c575173ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61278a3485613c98565b936040519485521692a2565b919081101561266e5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561019c570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c57602001918160051b3603831361019c57565b3573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c5760200191813603831361019c57565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561019c57016020813591019167ffffffffffffffff821161019c57813603831361019c57565b61012091813573ffffffffffffffffffffffffffffffffffffffff811680910361019c576129626129476129ba9561299b93855260208601356020860152612937604087018761289c565b9091806040880152860191612709565b612954606086018661289c565b908583036060870152612709565b6080840135608084015260a084013560a084015260c084013560c084015261298d60e085018561289c565b9084830360e0860152612709565b916129ac610100918281019061289c565b929091818503910152612709565b90565b60028054146129cc5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b926000905a93805194843573ffffffffffffffffffffffffffffffffffffffff811680910361019c5786526020850135602087015260808501356fffffffffffffffffffffffffffffffff90818116606089015260801c604088015260a086013560c088015260c086013590811661010088015260801c610120870152612a8060e086018661284b565b801561357b576034811061351d578060141161019c578060241161019c5760341161019c57602481013560801c60a0880152601481013560801c60808801523560601c60e08701525b612ad285612480565b60208301526040860151946effffffffffffffffffffffffffffff8660c08901511760608901511760808901511760a0890151176101008901511761012089015117116134bf57604087015160608801510160808801510160a08801510160c0880151016101008801510296835173ffffffffffffffffffffffffffffffffffffffff81511690612b66604085018561284b565b806131e4575b505060e0015173ffffffffffffffffffffffffffffffffffffffff1690600082156131ac575b6020612bd7918b828a01516000868a604051978896879586937f19822f7c00000000000000000000000000000000000000000000000000000000855260048501613db5565b0393f160009181613178575b50612c8b573d8c610800808311612c83575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612bf5565b9a92939495969798999a91156130f2575b509773ffffffffffffffffffffffffffffffffffffffff835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492612cee84612416565b9055160361308d575a8503116130285773ffffffffffffffffffffffffffffffffffffffff60e0606093015116612d42575b509060a09184959697986040608096015260608601520135905a900301910152565b969550505a9683519773ffffffffffffffffffffffffffffffffffffffff60e08a01511680600052600060205260406000208054848110612fc3576080612dcd9a9b9c600093878094039055015192602089015183604051809d819582947f52b7512c0000000000000000000000000000000000000000000000000000000084528c60048501613db5565b039286f1978860009160009a612f36575b50612e86573d8b610800808311612e7e575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612df0565b9991929394959697989998925a900311612eab57509096959094939291906080612d20565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b915098503d90816000823e612f4b82826121ed565b604081838101031261019c5780519067ffffffffffffffff821161019c57828101601f83830101121561019c578181015191612f868361222e565b93612f9460405195866121ed565b838552820160208483850101011161019c57602092612fba9184808701918501016123a3565b01519838612dde565b60848b604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808c11613113578b9003905538612c9c565b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b9091506020813d6020116131a4575b81613194602093836121ed565b8101031261019c57519038612be3565b3d9150613187565b508060005260006020526040600020548a81116000146131d75750612bd7602060005b915050612b92565b6020612bd7918c036131cf565b833b61345a57604088510151602060405180927f570e1a360000000000000000000000000000000000000000000000000000000082528260048301528160008161323260248201898b612709565b039273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c1690f1908115610db75760009161343b575b5073ffffffffffffffffffffffffffffffffffffffff811680156133d6578503613371573b1561330c5760141161019c5773ffffffffffffffffffffffffffffffffffffffff9183887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391612b6c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b60848e604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b60848f604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b613454915060203d602011610db057610da181836121ed565b3861327c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b5050600060e087015260006080870152600060a0870152612ac9565b9092915a906060810151916040928351967fffffffff00000000000000000000000000000000000000000000000000000000886135d7606084018461284b565b600060038211613b9f575b7f8dd7712f0000000000000000000000000000000000000000000000000000000094168403613a445750505061379d6000926136b292602088015161363a8a5193849360208501528b602485015260648401906128ec565b90604483015203906136727fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0928381018352826121ed565b61379189519485927e42dc5300000000000000000000000000000000000000000000000000000000602085015261020060248501526102248401906123c6565b613760604484018b60806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152876123c6565b039081018352826121ed565b6020918183809351910182305af1600051988652156137bf575b505050505050565b909192939495965060003d8214613a3a575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361385b57608487878051917f220266b600000000000000000000000000000000000000000000000000000000835260048301526024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b7fdeadaa510000000000000000000000000000000000000000000000000000000091929395949650146000146138c55750506138a961389e6138b8935a90612443565b608085015190612409565b9083015183611d748295613d65565b905b3880808080806137b7565b909261395290828601518651907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479273ffffffffffffffffffffffffffffffffffffffff9580878551169401516139483d610800808211613a32575b508a519084818301018c5280825260008583013e8a805194859485528401528a8301906123c6565b0390a35a90612443565b916139636080860193845190612409565b926000905a94829488519761397789613ccc565b948260e08b0151168015600014613a1857505050875116955b5a9003019560a06060820151910151019051860390818111613a04575b5050840290850151928184106000146139de57505080611e68575090816139d89293611d7481613d65565b906138ba565b6139ee9082849397950390613c98565b50611e68575090826139ff92613cf6565b6139d8565b6064919003600a02049094019338806139ad565b90919892509751613a2a575b50613990565b955038613a24565b905038613920565b8181803e516137d1565b613b97945082935090613a8c917e42dc53000000000000000000000000000000000000000000000000000000006020613b6b9501526102006024860152610224850191612709565b613b3a604484018860806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152846123c6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018952886121ed565b60008761379d565b5081356135e2565b73ffffffffffffffffffffffffffffffffffffffff168015613c3a57600080809381935af1613bd4612450565b5015613bdc57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff166000526000602052613cc66040600020918254612409565b80915590565b610120610100820151910151808214613cf257480180821015613ced575090565b905090565b5090565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff946020868851169660e089015116970151916040519283526000602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b613dcd604092959493956060835260608301906128ec565b9460208201520152565b8015613e6457600060408051613dec816121d1565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff811690604065ffffffffffff91828160a01c16908115613e5c575b60d01c92825191613e37836121d1565b8583528460208401521691829101524211908115613e5457509091565b905042109091565b839150613e27565b5060009060009056fea2646970667358221220b094fd69f04977ae9458e5ba422d01cd2d20dbcfca0992ff37f19aa07deec25464736f6c63430008170033", + "nonce": "2", + "storage": { + "0xa3b2ff63dddb6717733673f0c1cf67be4e4eecc50d4e5fd777cf82e814f7242f": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x7ab5742e5b448c142a35c92699fd2dd6b8930cbd": { + "balance": "0xfffffffffffffffffffffffffffffffffffffffffffffffb0dc02146cf089f65", + "nonce": "110" + } + }, + "config": { + "chainId": 1337, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "rip7560block": 0, + "rip7712block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "pragueTime": 0, + "terminalTotalDifficulty": 0, + "depositContractAddress": "0x0000000000000000000000000000000000000000", + "blobSchedule": { + "cancun": { + "max": 6, + "target": 3, + "baseFeeUpdateFraction": 3338477 + }, + "prague": { + "max": 9, + "target": 6, + "baseFeeUpdateFraction": 5007716 + } + } + } + }, + "context": { + "number": "115", + "difficulty": "0", + "timestamp": "1738267578", + "gasLimit": "30000000", + "miner": "0x0000000000000000000000000000000000000000", + "baseFeePerGas": "1457" + }, + "input": "0x02f8998205396e843b99d302843b99e00283023a3c940000000071727de22e5e9d8baf0edac6f37da032880de0b6b3a7640000a4b760faf90000000000000000000000005604b855b3708057705f8dfc0e6470917082c43ac001a03a94ab9585bd0a378ddfcaa078a3982bb88e60c22407de299ad314b8a8631a31a0720f8eb0d92906238bc842b387ee147519d9b05e22d8c77d5a855cb16744d660", + "result": { + "accessedSlots": { + "reads": { + "0xa3b2ff63dddb6717733673f0c1cf67be4e4eecc50d4e5fd777cf82e814f7242f": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + "transientReads": {}, + "transientWrites": {}, + "writes": { + "0xa3b2ff63dddb6717733673f0c1cf67be4e4eecc50d4e5fd777cf82e814f7242f": 1 + } + }, + "contractSize": {}, + "extCodeAccessInfo": [], + "from": "0x7ab5742e5b448c142a35c92699fd2dd6b8930cbd", + "gas": "0x23a3c", + "gasUsed": "0xb21f", + "input": "0xb760faf90000000000000000000000005604b855b3708057705f8dfc0e6470917082c43a", + "keccak": [ + "0x0000000000000000000000005604b855b3708057705f8dfc0e6470917082c43a0000000000000000000000000000000000000000000000000000000000000000" + ], + "outOfGas": false, + "to": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "type": "CALL", + "usedOpcodes": {"0x0":1, "0x20":1, "0x34":1, "0x35":2, "0x36":2, "0x51":1, "0x52":4, "0x54":1, "0x55":1, "0x56":8, "0x57":18, "0x5b":10, "0xa2":1}, + "value": "0xde0b6b3a7640000" + } +} diff --git a/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_paymaster.json b/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_paymaster.json new file mode 100644 index 0000000000..a7e09f761e --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_paymaster.json @@ -0,0 +1,110 @@ +{ + "genesis": { + "baseFeePerGas": "63230", + "blobGasUsed": "0", + "difficulty": "0", + "excessBlobGas": "0", + "extraData": "0xd883010e0d846765746888676f312e32322e36856c696e7578", + "gasLimit": "30000000", + "hash": "0x38e598c8c0600233b8353fb28aa12e987be7216fcb141cffb03d941141dac085", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0xc406f87ac4eb5e4d1d95345ceb92a3f17a7c97f6e9d4c1c857601960cd91d3b2", + "nonce": "0x0000000000000000", + "number": "84", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "stateRoot": "0xc0df2d6f5e7199feff4e49bf23d05f5758d85b146159b1b5b53700bee1b0c073", + "timestamp": "1738266969", + "withdrawals": [], + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "alloc": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x1fbe9bb2534e03d" + }, + "0x0000000071727de22e5e9d8baf0edac6f37da032": { + "balance": "0x3a21a6c6853747fff", + "code": "0x60806040526004361015610024575b361561001957600080fd5b61002233612748565b005b60003560e01c806242dc5314611b0057806301ffc9a7146119ae5780630396cb60146116765780630bd28e3b146115fa5780631b2e01b814611566578063205c2878146113d157806322cdde4c1461136b57806335567e1a146112b35780635287ce12146111a557806370a0823114611140578063765e827f14610e82578063850aaf6214610dc35780639b249f6914610c74578063b760faf914610c3a578063bb9fe6bf14610a68578063c23a5cea146107c4578063dbed18e0146101a15763fc7e286d0361000e573461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61013a61229f565b16600052600060205260a0604060002065ffffffffffff6001825492015460405192835260ff8116151560208401526dffffffffffffffffffffffffffff8160081c16604084015263ffffffff8160781c16606084015260981c166080820152f35b600080fd5b3461019c576101af36612317565b906101b86129bd565b60009160005b82811061056f57506101d08493612588565b6000805b8481106102fc5750507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000809360005b81811061024757610240868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2613ba7565b6001600255005b6102a261025582848a612796565b73ffffffffffffffffffffffffffffffffffffffff6102766020830161282a565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a2806127d6565b906000915b8083106102b957505050600101610209565b909194976102f36102ed6001926102e78c8b6102e0826102da8e8b8d61269d565b9261265a565b5191613597565b90612409565b99612416565b950191906102a7565b6020610309828789612796565b61031f61031682806127d6565b9390920161282a565b9160009273ffffffffffffffffffffffffffffffffffffffff8091165b8285106103505750505050506001016101d4565b909192939561037f83610378610366848c61265a565b516103728b898b61269d565b856129f6565b9290613dd7565b9116840361050a576104a5576103958491613dd7565b9116610440576103b5576103aa600191612416565b96019392919061033c565b60a487604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b61057a818487612796565b9361058585806127d6565b919095602073ffffffffffffffffffffffffffffffffffffffff6105aa82840161282a565b1697600192838a1461076657896105da575b5050505060019293949550906105d191612409565b939291016101be565b8060406105e892019061284b565b918a3b1561019c57929391906040519485937f2dd8113300000000000000000000000000000000000000000000000000000000855288604486016040600488015252606490818601918a60051b8701019680936000915b8c83106106e657505050505050838392610684927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8560009803016024860152612709565b03818a5afa90816106d7575b506106c657602486604051907f86a9f7500000000000000000000000000000000000000000000000000000000082526004820152fd5b93945084936105d1600189806105bc565b6106e0906121bd565b88610690565b91939596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c908a9294969a0301865288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181121561019c57836107538793858394016128ec565b9a0196019301909189979695949261063f565b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b3461019c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576107fc61229f565b33600052600082526001604060002001908154916dffffffffffffffffffffffffffff8360081c16928315610a0a5765ffffffffffff8160981c1680156109ac57421061094e5760009373ffffffffffffffffffffffffffffffffffffffff859485947fffffffffffffff000000000000000000000000000000000000000000000000ff86951690556040517fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda33391806108da8786836020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0390a2165af16108e8612450565b50156108f057005b606490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b3461019c5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c573360005260006020526001604060002001805463ffffffff8160781c16908115610bdc5760ff1615610b7e5765ffffffffffff908142160191818311610b4f5780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609885901b161790556040519116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a2005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610022610c6f61229f565b612748565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043567ffffffffffffffff811161019c576020610cc8610d1b9236906004016122c2565b919073ffffffffffffffffffffffffffffffffffffffff9260405194859283927f570e1a360000000000000000000000000000000000000000000000000000000084528560048501526024840191612709565b03816000857f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c165af1908115610db757602492600092610d86575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b610da991925060203d602011610db0575b610da181836121ed565b8101906126dd565b9083610d56565b503d610d97565b6040513d6000823e3d90fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610dfa61229f565b60243567ffffffffffffffff811161019c57600091610e1e839236906004016122c2565b90816040519283928337810184815203915af4610e39612450565b90610e7e6040519283927f99410554000000000000000000000000000000000000000000000000000000008452151560048401526040602484015260448301906123c6565b0390fd5b3461019c57610e9036612317565b610e9b9291926129bd565b610ea483612588565b60005b848110610f1c57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000915b858310610eec576102408585613ba7565b909193600190610f12610f0087898761269d565b610f0a888661265a565b519088613597565b0194019190610edb565b610f47610f40610f2e8385979561265a565b51610f3a84898761269d565b846129f6565b9190613dd7565b73ffffffffffffffffffffffffffffffffffffffff929183166110db5761107657610f7190613dd7565b911661101157610f8657600101929092610ea7565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61118c61229f565b1660005260006020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff6111f161229f565b6000608060405161120181612155565b828152826020820152826040820152826060820152015216600052600060205260a06040600020608060405161123681612155565b6001835493848352015490602081019060ff8316151582526dffffffffffffffffffffffffffff60408201818560081c16815263ffffffff936060840193858760781c16855265ffffffffffff978891019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760206112ec61229f565b73ffffffffffffffffffffffffffffffffffffffff6113096122f0565b911660005260018252604060002077ffffffffffffffffffffffffffffffffffffffffffffffff821660005282526040600020547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b3461019c577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60208136011261019c576004359067ffffffffffffffff821161019c5761012090823603011261019c576113c9602091600401612480565b604051908152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761140861229f565b60243590336000526000602052604060002090815491828411611508576000808573ffffffffffffffffffffffffffffffffffffffff8295839561144c848a612443565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af16114a2612450565b50156114aa57005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761159d61229f565b73ffffffffffffffffffffffffffffffffffffffff6115ba6122f0565b9116600052600160205277ffffffffffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043577ffffffffffffffffffffffffffffffffffffffffffffffff811680910361019c5733600052600160205260406000209060005260205260406000206116728154612416565b9055005b6020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043563ffffffff9182821680920361019c5733600052600081526040600020928215611950576001840154908160781c1683106118f2576116f86dffffffffffffffffffffffffffff9182349160081c16612409565b93841561189457818511611836579065ffffffffffff61180592546040519061172082612155565b8152848101926001845260408201908816815260608201878152600160808401936000855233600052600089526040600020905181550194511515917fffffffffffffffffffffffffff0000000000000000000000000000000000000060ff72ffffffff0000000000000000000000000000006effffffffffffffffffffffffffff008954945160081b16945160781b1694169116171717835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b6040519283528201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a2005b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019c57807f60fc6b6e0000000000000000000000000000000000000000000000000000000060209214908115611ad6575b8115611aac575b8115611a82575b8115611a58575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482611a4d565b7f3e84f0210000000000000000000000000000000000000000000000000000000081149150611a46565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150611a3f565b7f915074d80000000000000000000000000000000000000000000000000000000081149150611a38565b3461019c576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5767ffffffffffffffff60043581811161019c573660238201121561019c57611b62903690602481600401359101612268565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c0811261019c5761014060405191611b9e83612155565b1261019c5760405192611bb0846121a0565b60243573ffffffffffffffffffffffffffffffffffffffff8116810361019c578452602093604435858201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff8116810361019c5760e08201526101243561010082015261014435610120820152825261016435848301526101843560408301526101a43560608301526101c43560808301526101e43590811161019c57611c7c9036906004016122c2565b905a3033036120f7578351606081015195603f5a0260061c61271060a0840151890101116120ce5760009681519182611ff0575b5050505090611cca915a9003608085015101923691612268565b925a90600094845193611cdc85613ccc565b9173ffffffffffffffffffffffffffffffffffffffff60e0870151168015600014611ea957505073ffffffffffffffffffffffffffffffffffffffff855116935b5a9003019360a06060820151910151016080860151850390818111611e95575b50508302604085015192818410600014611dce5750506003811015611da157600203611d79576113c99293508093611d7481613d65565b613cf6565b5050507fdeadaa51000000000000000000000000000000000000000000000000000000008152fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b81611dde92979396940390613c98565b506003841015611e6857507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f60808683015192519473ffffffffffffffffffffffffffffffffffffffff865116948873ffffffffffffffffffffffffffffffffffffffff60e0890151169701519160405192835215898301528760408301526060820152a46113c9565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b6064919003600a0204909301928780611d3d565b8095918051611eba575b5050611d1d565b6003861015611fc1576002860315611eb35760a088015190823b1561019c57600091611f2491836040519586809581947f7c627b210000000000000000000000000000000000000000000000000000000083528d60048401526080602484015260848301906123c6565b8b8b0260448301528b60648301520393f19081611fad575b50611fa65787893d610800808211611f9e575b506040519282828501016040528184528284013e610e7e6040519283927fad7954bc000000000000000000000000000000000000000000000000000000008452600484015260248301906123c6565b905083611f4f565b8980611eb3565b611fb89199506121bd565b6000978a611f3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91600092918380938c73ffffffffffffffffffffffffffffffffffffffff885116910192f115612023575b808080611cb0565b611cca929195503d6108008082116120c6575b5060405190888183010160405280825260008983013e805161205f575b5050600194909161201b565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20188870151918973ffffffffffffffffffffffffffffffffffffffff8551169401516120bc604051928392835260408d84015260408301906123c6565b0390a38680612053565b905088612036565b877fdeaddead000000000000000000000000000000000000000000000000000000006000526000fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff82111761217157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610140810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157604052565b6060810190811067ffffffffffffffff82111761217157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926122748261222e565b9161228260405193846121ed565b82948184528183011161019c578281602093846000960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9181601f8401121561019c5782359167ffffffffffffffff831161019c576020838186019501011161019c57565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261019c5760043567ffffffffffffffff9283821161019c578060238301121561019c57816004013593841161019c5760248460051b8301011161019c57602401919060243573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b60005b8381106123b65750506000910152565b81810151838201526020016123a6565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093612402815180928187528780880191016123a3565b0116010190565b91908201809211610b4f57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610b4f5760010190565b91908203918211610b4f57565b3d1561247b573d906124618261222e565b9161246f60405193846121ed565b82523d6000602084013e565b606090565b604061248e8183018361284b565b90818351918237206124a3606084018461284b565b90818451918237209260c06124bb60e083018361284b565b908186519182372091845195602087019473ffffffffffffffffffffffffffffffffffffffff833516865260208301358789015260608801526080870152608081013560a087015260a081013582870152013560e08501526101009081850152835261012083019167ffffffffffffffff918484108385111761217157838252845190206101408501908152306101608601524661018086015260608452936101a00191821183831017612171575251902090565b67ffffffffffffffff81116121715760051b60200190565b9061259282612570565b6040906125a260405191826121ed565b8381527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06125d08295612570565b019160005b8381106125e25750505050565b60209082516125f081612155565b83516125fb816121a0565b600081526000849181838201528187820152816060818184015260809282848201528260a08201528260c08201528260e082015282610100820152826101208201528652818587015281898701528501528301528286010152016125d5565b805182101561266e5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919081101561266e5760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18136030182121561019c570190565b9081602091031261019c575173ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61278a3485613c98565b936040519485521692a2565b919081101561266e5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561019c570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c57602001918160051b3603831361019c57565b3573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c5760200191813603831361019c57565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561019c57016020813591019167ffffffffffffffff821161019c57813603831361019c57565b61012091813573ffffffffffffffffffffffffffffffffffffffff811680910361019c576129626129476129ba9561299b93855260208601356020860152612937604087018761289c565b9091806040880152860191612709565b612954606086018661289c565b908583036060870152612709565b6080840135608084015260a084013560a084015260c084013560c084015261298d60e085018561289c565b9084830360e0860152612709565b916129ac610100918281019061289c565b929091818503910152612709565b90565b60028054146129cc5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b926000905a93805194843573ffffffffffffffffffffffffffffffffffffffff811680910361019c5786526020850135602087015260808501356fffffffffffffffffffffffffffffffff90818116606089015260801c604088015260a086013560c088015260c086013590811661010088015260801c610120870152612a8060e086018661284b565b801561357b576034811061351d578060141161019c578060241161019c5760341161019c57602481013560801c60a0880152601481013560801c60808801523560601c60e08701525b612ad285612480565b60208301526040860151946effffffffffffffffffffffffffffff8660c08901511760608901511760808901511760a0890151176101008901511761012089015117116134bf57604087015160608801510160808801510160a08801510160c0880151016101008801510296835173ffffffffffffffffffffffffffffffffffffffff81511690612b66604085018561284b565b806131e4575b505060e0015173ffffffffffffffffffffffffffffffffffffffff1690600082156131ac575b6020612bd7918b828a01516000868a604051978896879586937f19822f7c00000000000000000000000000000000000000000000000000000000855260048501613db5565b0393f160009181613178575b50612c8b573d8c610800808311612c83575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612bf5565b9a92939495969798999a91156130f2575b509773ffffffffffffffffffffffffffffffffffffffff835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492612cee84612416565b9055160361308d575a8503116130285773ffffffffffffffffffffffffffffffffffffffff60e0606093015116612d42575b509060a09184959697986040608096015260608601520135905a900301910152565b969550505a9683519773ffffffffffffffffffffffffffffffffffffffff60e08a01511680600052600060205260406000208054848110612fc3576080612dcd9a9b9c600093878094039055015192602089015183604051809d819582947f52b7512c0000000000000000000000000000000000000000000000000000000084528c60048501613db5565b039286f1978860009160009a612f36575b50612e86573d8b610800808311612e7e575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612df0565b9991929394959697989998925a900311612eab57509096959094939291906080612d20565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b915098503d90816000823e612f4b82826121ed565b604081838101031261019c5780519067ffffffffffffffff821161019c57828101601f83830101121561019c578181015191612f868361222e565b93612f9460405195866121ed565b838552820160208483850101011161019c57602092612fba9184808701918501016123a3565b01519838612dde565b60848b604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808c11613113578b9003905538612c9c565b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b9091506020813d6020116131a4575b81613194602093836121ed565b8101031261019c57519038612be3565b3d9150613187565b508060005260006020526040600020548a81116000146131d75750612bd7602060005b915050612b92565b6020612bd7918c036131cf565b833b61345a57604088510151602060405180927f570e1a360000000000000000000000000000000000000000000000000000000082528260048301528160008161323260248201898b612709565b039273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c1690f1908115610db75760009161343b575b5073ffffffffffffffffffffffffffffffffffffffff811680156133d6578503613371573b1561330c5760141161019c5773ffffffffffffffffffffffffffffffffffffffff9183887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391612b6c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b60848e604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b60848f604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b613454915060203d602011610db057610da181836121ed565b3861327c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b5050600060e087015260006080870152600060a0870152612ac9565b9092915a906060810151916040928351967fffffffff00000000000000000000000000000000000000000000000000000000886135d7606084018461284b565b600060038211613b9f575b7f8dd7712f0000000000000000000000000000000000000000000000000000000094168403613a445750505061379d6000926136b292602088015161363a8a5193849360208501528b602485015260648401906128ec565b90604483015203906136727fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0928381018352826121ed565b61379189519485927e42dc5300000000000000000000000000000000000000000000000000000000602085015261020060248501526102248401906123c6565b613760604484018b60806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152876123c6565b039081018352826121ed565b6020918183809351910182305af1600051988652156137bf575b505050505050565b909192939495965060003d8214613a3a575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361385b57608487878051917f220266b600000000000000000000000000000000000000000000000000000000835260048301526024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b7fdeadaa510000000000000000000000000000000000000000000000000000000091929395949650146000146138c55750506138a961389e6138b8935a90612443565b608085015190612409565b9083015183611d748295613d65565b905b3880808080806137b7565b909261395290828601518651907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479273ffffffffffffffffffffffffffffffffffffffff9580878551169401516139483d610800808211613a32575b508a519084818301018c5280825260008583013e8a805194859485528401528a8301906123c6565b0390a35a90612443565b916139636080860193845190612409565b926000905a94829488519761397789613ccc565b948260e08b0151168015600014613a1857505050875116955b5a9003019560a06060820151910151019051860390818111613a04575b5050840290850151928184106000146139de57505080611e68575090816139d89293611d7481613d65565b906138ba565b6139ee9082849397950390613c98565b50611e68575090826139ff92613cf6565b6139d8565b6064919003600a02049094019338806139ad565b90919892509751613a2a575b50613990565b955038613a24565b905038613920565b8181803e516137d1565b613b97945082935090613a8c917e42dc53000000000000000000000000000000000000000000000000000000006020613b6b9501526102006024860152610224850191612709565b613b3a604484018860806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152846123c6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018952886121ed565b60008761379d565b5081356135e2565b73ffffffffffffffffffffffffffffffffffffffff168015613c3a57600080809381935af1613bd4612450565b5015613bdc57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff166000526000602052613cc66040600020918254612409565b80915590565b610120610100820151910151808214613cf257480180821015613ced575090565b905090565b5090565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff946020868851169660e089015116970151916040519283526000602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b613dcd604092959493956060835260608301906128ec565b9460208201520152565b8015613e6457600060408051613dec816121d1565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff811690604065ffffffffffff91828160a01c16908115613e5c575b60d01c92825191613e37836121d1565b8583528460208401521691829101524211908115613e5457509091565b905042109091565b839150613e27565b5060009060009056fea2646970667358221220b094fd69f04977ae9458e5ba422d01cd2d20dbcfca0992ff37f19aa07deec25464736f6c63430008170033", + "nonce": "2", + "storage": { + "0xfd8a9a5105ec447cdc63b84f6e5700b432121f67627f5d0269ac1b8f5e1b5507": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x7ab5742e5b448c142a35c92699fd2dd6b8930cbd": { + "balance": "0xfffffffffffffffffffffffffffffffffffffffffffffffc4dc3b19c23c7dc28", + "nonce": "81" + } + }, + "config": { + "chainId": 1337, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "rip7560block": 0, + "rip7712block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "pragueTime": 0, + "terminalTotalDifficulty": 0, + "depositContractAddress": "0x0000000000000000000000000000000000000000", + "blobSchedule": { + "cancun": { + "max": 6, + "target": 3, + "baseFeeUpdateFraction": 3338477 + }, + "prague": { + "max": 9, + "target": 6, + "baseFeeUpdateFraction": 5007716 + } + } + } + }, + "context": { + "number": "85", + "difficulty": "0", + "timestamp": "1738266970", + "gasLimit": "30000000", + "miner": "0x0000000000000000000000000000000000000000", + "baseFeePerGas": "55726" + }, + "input": "0x02f89882053951843b82b63d843b84a43983023a3c940000000071727de22e5e9d8baf0edac6f37da032874a9b6384487fffa4b760faf900000000000000000000000093e4af629481a69da4e7335892703ae52113b3e7c001a003d55576c3186202ffa9e00ea2ef84b3699ec1a77285a8a54876915689c8e946a00e59f2fdddd26270454a759c24609bd8eb20b899f8d2a99922c3a3adc586e366", + "result": { + "accessedSlots": { + "reads": { + "0xfd8a9a5105ec447cdc63b84f6e5700b432121f67627f5d0269ac1b8f5e1b5507": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + "transientReads": {}, + "transientWrites": {}, + "writes": { + "0xfd8a9a5105ec447cdc63b84f6e5700b432121f67627f5d0269ac1b8f5e1b5507": 1 + } + }, + "contractSize": {}, + "extCodeAccessInfo": [], + "from": "0x7ab5742e5b448c142a35c92699fd2dd6b8930cbd", + "gas": "0x23a3c", + "gasUsed": "0xb21f", + "input": "0xb760faf900000000000000000000000093e4af629481a69da4e7335892703ae52113b3e7", + "keccak": [ + "0x00000000000000000000000093e4af629481a69da4e7335892703ae52113b3e70000000000000000000000000000000000000000000000000000000000000000" + ], + "outOfGas": false, + "to": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "type": "CALL", + "usedOpcodes": {"0x0":1, "0x20":1, "0x34":1, "0x35":2, "0x36":2, "0x51":1, "0x52":4, "0x54":1, "0x55":1, "0x56":8, "0x57":18, "0x5b":10, "0xa2":1}, + "value": "0x4a9b6384487fff" + } +} diff --git a/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_simple.json b/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_simple.json new file mode 100644 index 0000000000..f0a0fc1655 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/erc7562_tracer/erc7562Tracer.test_simple.json @@ -0,0 +1,246 @@ +{ + "genesis": { + "baseFeePerGas": "42949", + "blobGasUsed": "0", + "difficulty": "0", + "excessBlobGas": "0", + "extraData": "0xd883010e0d846765746888676f312e32322e36856c696e7578", + "gasLimit": "30000000", + "hash": "0x6f85304f332c41070b645fbed7ad468db1f80d3b52776d8a3f3c10c9d106db17", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x4917b13b44dc41c98ec2099dd0f549c640b98d3e358cc7fcdef7988153093510", + "nonce": "0x0000000000000000", + "number": "87", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "stateRoot": "0xb17f1114a85e834ee373ad5be38854b7efc921bdcef77acef657fdc63ab25cf8", + "timestamp": "1738267404", + "withdrawals": [], + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "alloc": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x20113869f420bed" + }, + "0x0000000071727de22e5e9d8baf0edac6f37da032": { + "balance": "0x3be2675332684fffe", + "code": "0x60806040526004361015610024575b361561001957600080fd5b61002233612748565b005b60003560e01c806242dc5314611b0057806301ffc9a7146119ae5780630396cb60146116765780630bd28e3b146115fa5780631b2e01b814611566578063205c2878146113d157806322cdde4c1461136b57806335567e1a146112b35780635287ce12146111a557806370a0823114611140578063765e827f14610e82578063850aaf6214610dc35780639b249f6914610c74578063b760faf914610c3a578063bb9fe6bf14610a68578063c23a5cea146107c4578063dbed18e0146101a15763fc7e286d0361000e573461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61013a61229f565b16600052600060205260a0604060002065ffffffffffff6001825492015460405192835260ff8116151560208401526dffffffffffffffffffffffffffff8160081c16604084015263ffffffff8160781c16606084015260981c166080820152f35b600080fd5b3461019c576101af36612317565b906101b86129bd565b60009160005b82811061056f57506101d08493612588565b6000805b8481106102fc5750507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000809360005b81811061024757610240868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2613ba7565b6001600255005b6102a261025582848a612796565b73ffffffffffffffffffffffffffffffffffffffff6102766020830161282a565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a2806127d6565b906000915b8083106102b957505050600101610209565b909194976102f36102ed6001926102e78c8b6102e0826102da8e8b8d61269d565b9261265a565b5191613597565b90612409565b99612416565b950191906102a7565b6020610309828789612796565b61031f61031682806127d6565b9390920161282a565b9160009273ffffffffffffffffffffffffffffffffffffffff8091165b8285106103505750505050506001016101d4565b909192939561037f83610378610366848c61265a565b516103728b898b61269d565b856129f6565b9290613dd7565b9116840361050a576104a5576103958491613dd7565b9116610440576103b5576103aa600191612416565b96019392919061033c565b60a487604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b61057a818487612796565b9361058585806127d6565b919095602073ffffffffffffffffffffffffffffffffffffffff6105aa82840161282a565b1697600192838a1461076657896105da575b5050505060019293949550906105d191612409565b939291016101be565b8060406105e892019061284b565b918a3b1561019c57929391906040519485937f2dd8113300000000000000000000000000000000000000000000000000000000855288604486016040600488015252606490818601918a60051b8701019680936000915b8c83106106e657505050505050838392610684927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8560009803016024860152612709565b03818a5afa90816106d7575b506106c657602486604051907f86a9f7500000000000000000000000000000000000000000000000000000000082526004820152fd5b93945084936105d1600189806105bc565b6106e0906121bd565b88610690565b91939596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c908a9294969a0301865288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181121561019c57836107538793858394016128ec565b9a0196019301909189979695949261063f565b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b3461019c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576107fc61229f565b33600052600082526001604060002001908154916dffffffffffffffffffffffffffff8360081c16928315610a0a5765ffffffffffff8160981c1680156109ac57421061094e5760009373ffffffffffffffffffffffffffffffffffffffff859485947fffffffffffffff000000000000000000000000000000000000000000000000ff86951690556040517fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda33391806108da8786836020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0390a2165af16108e8612450565b50156108f057005b606490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b3461019c5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c573360005260006020526001604060002001805463ffffffff8160781c16908115610bdc5760ff1615610b7e5765ffffffffffff908142160191818311610b4f5780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609885901b161790556040519116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a2005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610022610c6f61229f565b612748565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043567ffffffffffffffff811161019c576020610cc8610d1b9236906004016122c2565b919073ffffffffffffffffffffffffffffffffffffffff9260405194859283927f570e1a360000000000000000000000000000000000000000000000000000000084528560048501526024840191612709565b03816000857f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c165af1908115610db757602492600092610d86575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b610da991925060203d602011610db0575b610da181836121ed565b8101906126dd565b9083610d56565b503d610d97565b6040513d6000823e3d90fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610dfa61229f565b60243567ffffffffffffffff811161019c57600091610e1e839236906004016122c2565b90816040519283928337810184815203915af4610e39612450565b90610e7e6040519283927f99410554000000000000000000000000000000000000000000000000000000008452151560048401526040602484015260448301906123c6565b0390fd5b3461019c57610e9036612317565b610e9b9291926129bd565b610ea483612588565b60005b848110610f1c57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000915b858310610eec576102408585613ba7565b909193600190610f12610f0087898761269d565b610f0a888661265a565b519088613597565b0194019190610edb565b610f47610f40610f2e8385979561265a565b51610f3a84898761269d565b846129f6565b9190613dd7565b73ffffffffffffffffffffffffffffffffffffffff929183166110db5761107657610f7190613dd7565b911661101157610f8657600101929092610ea7565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61118c61229f565b1660005260006020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff6111f161229f565b6000608060405161120181612155565b828152826020820152826040820152826060820152015216600052600060205260a06040600020608060405161123681612155565b6001835493848352015490602081019060ff8316151582526dffffffffffffffffffffffffffff60408201818560081c16815263ffffffff936060840193858760781c16855265ffffffffffff978891019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760206112ec61229f565b73ffffffffffffffffffffffffffffffffffffffff6113096122f0565b911660005260018252604060002077ffffffffffffffffffffffffffffffffffffffffffffffff821660005282526040600020547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b3461019c577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60208136011261019c576004359067ffffffffffffffff821161019c5761012090823603011261019c576113c9602091600401612480565b604051908152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761140861229f565b60243590336000526000602052604060002090815491828411611508576000808573ffffffffffffffffffffffffffffffffffffffff8295839561144c848a612443565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af16114a2612450565b50156114aa57005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761159d61229f565b73ffffffffffffffffffffffffffffffffffffffff6115ba6122f0565b9116600052600160205277ffffffffffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043577ffffffffffffffffffffffffffffffffffffffffffffffff811680910361019c5733600052600160205260406000209060005260205260406000206116728154612416565b9055005b6020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043563ffffffff9182821680920361019c5733600052600081526040600020928215611950576001840154908160781c1683106118f2576116f86dffffffffffffffffffffffffffff9182349160081c16612409565b93841561189457818511611836579065ffffffffffff61180592546040519061172082612155565b8152848101926001845260408201908816815260608201878152600160808401936000855233600052600089526040600020905181550194511515917fffffffffffffffffffffffffff0000000000000000000000000000000000000060ff72ffffffff0000000000000000000000000000006effffffffffffffffffffffffffff008954945160081b16945160781b1694169116171717835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b6040519283528201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a2005b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019c57807f60fc6b6e0000000000000000000000000000000000000000000000000000000060209214908115611ad6575b8115611aac575b8115611a82575b8115611a58575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482611a4d565b7f3e84f0210000000000000000000000000000000000000000000000000000000081149150611a46565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150611a3f565b7f915074d80000000000000000000000000000000000000000000000000000000081149150611a38565b3461019c576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5767ffffffffffffffff60043581811161019c573660238201121561019c57611b62903690602481600401359101612268565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c0811261019c5761014060405191611b9e83612155565b1261019c5760405192611bb0846121a0565b60243573ffffffffffffffffffffffffffffffffffffffff8116810361019c578452602093604435858201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff8116810361019c5760e08201526101243561010082015261014435610120820152825261016435848301526101843560408301526101a43560608301526101c43560808301526101e43590811161019c57611c7c9036906004016122c2565b905a3033036120f7578351606081015195603f5a0260061c61271060a0840151890101116120ce5760009681519182611ff0575b5050505090611cca915a9003608085015101923691612268565b925a90600094845193611cdc85613ccc565b9173ffffffffffffffffffffffffffffffffffffffff60e0870151168015600014611ea957505073ffffffffffffffffffffffffffffffffffffffff855116935b5a9003019360a06060820151910151016080860151850390818111611e95575b50508302604085015192818410600014611dce5750506003811015611da157600203611d79576113c99293508093611d7481613d65565b613cf6565b5050507fdeadaa51000000000000000000000000000000000000000000000000000000008152fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b81611dde92979396940390613c98565b506003841015611e6857507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f60808683015192519473ffffffffffffffffffffffffffffffffffffffff865116948873ffffffffffffffffffffffffffffffffffffffff60e0890151169701519160405192835215898301528760408301526060820152a46113c9565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b6064919003600a0204909301928780611d3d565b8095918051611eba575b5050611d1d565b6003861015611fc1576002860315611eb35760a088015190823b1561019c57600091611f2491836040519586809581947f7c627b210000000000000000000000000000000000000000000000000000000083528d60048401526080602484015260848301906123c6565b8b8b0260448301528b60648301520393f19081611fad575b50611fa65787893d610800808211611f9e575b506040519282828501016040528184528284013e610e7e6040519283927fad7954bc000000000000000000000000000000000000000000000000000000008452600484015260248301906123c6565b905083611f4f565b8980611eb3565b611fb89199506121bd565b6000978a611f3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91600092918380938c73ffffffffffffffffffffffffffffffffffffffff885116910192f115612023575b808080611cb0565b611cca929195503d6108008082116120c6575b5060405190888183010160405280825260008983013e805161205f575b5050600194909161201b565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20188870151918973ffffffffffffffffffffffffffffffffffffffff8551169401516120bc604051928392835260408d84015260408301906123c6565b0390a38680612053565b905088612036565b877fdeaddead000000000000000000000000000000000000000000000000000000006000526000fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff82111761217157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610140810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157604052565b6060810190811067ffffffffffffffff82111761217157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926122748261222e565b9161228260405193846121ed565b82948184528183011161019c578281602093846000960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9181601f8401121561019c5782359167ffffffffffffffff831161019c576020838186019501011161019c57565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261019c5760043567ffffffffffffffff9283821161019c578060238301121561019c57816004013593841161019c5760248460051b8301011161019c57602401919060243573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b60005b8381106123b65750506000910152565b81810151838201526020016123a6565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093612402815180928187528780880191016123a3565b0116010190565b91908201809211610b4f57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610b4f5760010190565b91908203918211610b4f57565b3d1561247b573d906124618261222e565b9161246f60405193846121ed565b82523d6000602084013e565b606090565b604061248e8183018361284b565b90818351918237206124a3606084018461284b565b90818451918237209260c06124bb60e083018361284b565b908186519182372091845195602087019473ffffffffffffffffffffffffffffffffffffffff833516865260208301358789015260608801526080870152608081013560a087015260a081013582870152013560e08501526101009081850152835261012083019167ffffffffffffffff918484108385111761217157838252845190206101408501908152306101608601524661018086015260608452936101a00191821183831017612171575251902090565b67ffffffffffffffff81116121715760051b60200190565b9061259282612570565b6040906125a260405191826121ed565b8381527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06125d08295612570565b019160005b8381106125e25750505050565b60209082516125f081612155565b83516125fb816121a0565b600081526000849181838201528187820152816060818184015260809282848201528260a08201528260c08201528260e082015282610100820152826101208201528652818587015281898701528501528301528286010152016125d5565b805182101561266e5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919081101561266e5760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18136030182121561019c570190565b9081602091031261019c575173ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61278a3485613c98565b936040519485521692a2565b919081101561266e5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561019c570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c57602001918160051b3603831361019c57565b3573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c5760200191813603831361019c57565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561019c57016020813591019167ffffffffffffffff821161019c57813603831361019c57565b61012091813573ffffffffffffffffffffffffffffffffffffffff811680910361019c576129626129476129ba9561299b93855260208601356020860152612937604087018761289c565b9091806040880152860191612709565b612954606086018661289c565b908583036060870152612709565b6080840135608084015260a084013560a084015260c084013560c084015261298d60e085018561289c565b9084830360e0860152612709565b916129ac610100918281019061289c565b929091818503910152612709565b90565b60028054146129cc5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b926000905a93805194843573ffffffffffffffffffffffffffffffffffffffff811680910361019c5786526020850135602087015260808501356fffffffffffffffffffffffffffffffff90818116606089015260801c604088015260a086013560c088015260c086013590811661010088015260801c610120870152612a8060e086018661284b565b801561357b576034811061351d578060141161019c578060241161019c5760341161019c57602481013560801c60a0880152601481013560801c60808801523560601c60e08701525b612ad285612480565b60208301526040860151946effffffffffffffffffffffffffffff8660c08901511760608901511760808901511760a0890151176101008901511761012089015117116134bf57604087015160608801510160808801510160a08801510160c0880151016101008801510296835173ffffffffffffffffffffffffffffffffffffffff81511690612b66604085018561284b565b806131e4575b505060e0015173ffffffffffffffffffffffffffffffffffffffff1690600082156131ac575b6020612bd7918b828a01516000868a604051978896879586937f19822f7c00000000000000000000000000000000000000000000000000000000855260048501613db5565b0393f160009181613178575b50612c8b573d8c610800808311612c83575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612bf5565b9a92939495969798999a91156130f2575b509773ffffffffffffffffffffffffffffffffffffffff835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492612cee84612416565b9055160361308d575a8503116130285773ffffffffffffffffffffffffffffffffffffffff60e0606093015116612d42575b509060a09184959697986040608096015260608601520135905a900301910152565b969550505a9683519773ffffffffffffffffffffffffffffffffffffffff60e08a01511680600052600060205260406000208054848110612fc3576080612dcd9a9b9c600093878094039055015192602089015183604051809d819582947f52b7512c0000000000000000000000000000000000000000000000000000000084528c60048501613db5565b039286f1978860009160009a612f36575b50612e86573d8b610800808311612e7e575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612df0565b9991929394959697989998925a900311612eab57509096959094939291906080612d20565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b915098503d90816000823e612f4b82826121ed565b604081838101031261019c5780519067ffffffffffffffff821161019c57828101601f83830101121561019c578181015191612f868361222e565b93612f9460405195866121ed565b838552820160208483850101011161019c57602092612fba9184808701918501016123a3565b01519838612dde565b60848b604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808c11613113578b9003905538612c9c565b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b9091506020813d6020116131a4575b81613194602093836121ed565b8101031261019c57519038612be3565b3d9150613187565b508060005260006020526040600020548a81116000146131d75750612bd7602060005b915050612b92565b6020612bd7918c036131cf565b833b61345a57604088510151602060405180927f570e1a360000000000000000000000000000000000000000000000000000000082528260048301528160008161323260248201898b612709565b039273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c1690f1908115610db75760009161343b575b5073ffffffffffffffffffffffffffffffffffffffff811680156133d6578503613371573b1561330c5760141161019c5773ffffffffffffffffffffffffffffffffffffffff9183887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391612b6c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b60848e604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b60848f604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b613454915060203d602011610db057610da181836121ed565b3861327c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b5050600060e087015260006080870152600060a0870152612ac9565b9092915a906060810151916040928351967fffffffff00000000000000000000000000000000000000000000000000000000886135d7606084018461284b565b600060038211613b9f575b7f8dd7712f0000000000000000000000000000000000000000000000000000000094168403613a445750505061379d6000926136b292602088015161363a8a5193849360208501528b602485015260648401906128ec565b90604483015203906136727fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0928381018352826121ed565b61379189519485927e42dc5300000000000000000000000000000000000000000000000000000000602085015261020060248501526102248401906123c6565b613760604484018b60806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152876123c6565b039081018352826121ed565b6020918183809351910182305af1600051988652156137bf575b505050505050565b909192939495965060003d8214613a3a575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361385b57608487878051917f220266b600000000000000000000000000000000000000000000000000000000835260048301526024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b7fdeadaa510000000000000000000000000000000000000000000000000000000091929395949650146000146138c55750506138a961389e6138b8935a90612443565b608085015190612409565b9083015183611d748295613d65565b905b3880808080806137b7565b909261395290828601518651907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479273ffffffffffffffffffffffffffffffffffffffff9580878551169401516139483d610800808211613a32575b508a519084818301018c5280825260008583013e8a805194859485528401528a8301906123c6565b0390a35a90612443565b916139636080860193845190612409565b926000905a94829488519761397789613ccc565b948260e08b0151168015600014613a1857505050875116955b5a9003019560a06060820151910151019051860390818111613a04575b5050840290850151928184106000146139de57505080611e68575090816139d89293611d7481613d65565b906138ba565b6139ee9082849397950390613c98565b50611e68575090826139ff92613cf6565b6139d8565b6064919003600a02049094019338806139ad565b90919892509751613a2a575b50613990565b955038613a24565b905038613920565b8181803e516137d1565b613b97945082935090613a8c917e42dc53000000000000000000000000000000000000000000000000000000006020613b6b9501526102006024860152610224850191612709565b613b3a604484018860806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152846123c6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018952886121ed565b60008761379d565b5081356135e2565b73ffffffffffffffffffffffffffffffffffffffff168015613c3a57600080809381935af1613bd4612450565b5015613bdc57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff166000526000602052613cc66040600020918254612409565b80915590565b610120610100820151910151808214613cf257480180821015613ced575090565b905090565b5090565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff946020868851169660e089015116970151916040519283526000602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b613dcd604092959493956060835260608301906128ec565b9460208201520152565b8015613e6457600060408051613dec816121d1565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff811690604065ffffffffffff91828160a01c16908115613e5c575b60d01c92825191613e37836121d1565b8583528460208401521691829101524211908115613e5457509091565b905042109091565b839150613e27565b5060009060009056fea2646970667358221220b094fd69f04977ae9458e5ba422d01cd2d20dbcfca0992ff37f19aa07deec25464736f6c63430008170033", + "nonce": "2", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x83d2064309e31181791f895d99cc244865c480f99200cd4d4f2412a7a3a265b6": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xe18cacf0f1fc038f916461d29104232bd93d822359dfc137927858cc71f1e4ed": "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + } + }, + "0x8c9d927336adc963536122f8e0d269319e79ed7a": { + "balance": "0x0", + "code": "0x60806040526004361015610015575b3661039257005b61001f5f3561007e565b806319822f7c14610079578063408aee4214610074578063451711591461006f578063a9cc47181461006a578063a9e966b7146100655763c19d93fb0361000e5761035d565b6102ee565b6102b6565b61028c565b6101b3565b61016e565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90816101209103126100a95790565b610096565b90565b6100ba816100ae565b036100c157565b5f80fd5b905035906100d2826100b1565b565b90565b6100e0816100d4565b036100e757565b5f80fd5b905035906100f8826100d7565b565b9091606082840312610147575f82013567ffffffffffffffff8111610142576101288461013f92850161009a565b9361013681602086016100c5565b936040016100eb565b90565b610092565b61008e565b610155906100d4565b9052565b919061016c905f6020850194019061014c565b565b3461019f5761019b61018a6101843660046100fa565b916107d1565b610192610084565b91829182610159565b0390f35b61008a565b5f9103126101ae57565b61008e565b346101e3576101c33660046101a4565b6101df6101ce610988565b6101d6610084565b91829182610159565b0390f35b61008a565b60018060a01b031690565b6101fc906101e8565b90565b610208906101f3565b90565b610214816101ff565b0361021b57565b5f80fd5b9050359061022c8261020b565b565b63ffffffff1690565b6102408161022e565b0361024757565b5f80fd5b9050359061025882610237565b565b9190604083820312610282578061027661027f925f860161021f565b9360200161024b565b90565b61008e565b5f0190565b6102a061029a36600461025a565b906109de565b6102a8610084565b806102b281610287565b0390f35b346102cb576102c63660046101a4565b610ac3565b61008a565b906020828203126102e9576102e6915f016100eb565b90565b61008e565b3461031c576103066103013660046102d0565b610b3f565b61030e610084565b8061031881610287565b0390f35b61008a565b1c90565b90565b61033890600861033d9302610321565b610325565b90565b9061034b9154610328565b90565b61035a60015f90610340565b90565b3461038d5761036d3660046101a4565b61038961037861034e565b610380610084565b91829182610159565b0390f35b61008a565b5f80fd5b5f90565b5f80fd5b5f80fd5b5f80fd5b9035906001602003813603038212156103e8570180359067ffffffffffffffff82116103e3576020019160018202360383136103de57565b6103a2565b61039e565b61039a565b5090565b90565b90565b61040b610406610410926103f1565b6103f4565b6100d4565b90565b6bffffffffffffffffffffffff191690565b1b90565b9061043761043e91836103ed565b9135610413565b906014811061044c575b5090565b61046a906bffffffffffffffffffffffff1990601403600802610425565b165f610448565b60601c90565b61048b610486610490926101e8565b6103f4565b6101e8565b90565b61049f6104a491610471565b610477565b90565b6104b090610493565b90565b6104bc90610477565b90565b6104c8906104b3565b90565b6104d490610477565b90565b6104e0906104cb565b90565b6104ec906104cb565b90565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b9061051b906104f3565b810190811067ffffffffffffffff82111761053557604052565b6104fd565b60e01b90565b9050519061054d826100d7565b565b9060208282031261056857610565915f01610540565b90565b61008e565b610576906101f3565b9052565b919061058d905f6020850194019061056d565b565b610597610084565b3d5f823e3d90fd5b90565b6105b66105b16105bb9261059f565b6103f4565b6100d4565b90565b905090565b6105ce5f80926105be565b0190565b6105db906105c3565b90565b906105f16105ea610084565b9283610511565b565b67ffffffffffffffff81116106115761060d6020916104f3565b0190565b6104fd565b90610628610623836105f3565b6105de565b918252565b606090565b3d5f1461064d576106423d610616565b903d5f602084013e5b565b61065561062d565b9061064b565b61ffff60f01b1690565b9061067361067a91836103ed565b913561065b565b9060028110610688575b5090565b61069e9061ffff60f01b90600203600802610425565b165f610684565b90565b60f01b90565b6106c26106bd6106c7926106a5565b6106a8565b61065b565b90565b60209181520190565b5f7f7465737457616c6c65743a2064656164207369676e6174757265000000000000910152565b610707601a6020926106ca565b610710816106d3565b0190565b6107299060208101905f8183039101526106fa565b90565b1561073357565b61073b610084565b62461bcd60e51b81528061075160048201610714565b0390fd5b90565b61076c61076761077192610755565b6106a8565b61065b565b90565b60ff1690565b61078e6107896107939261059f565b6103f4565b610774565b90565b90565b6107ad6107a86107b292610796565b6103f4565b610774565b90565b6107c96107c46107ce92610774565b6103f4565b6100d4565b90565b9190506107dc610396565b506107f46107ee8360608101906103a6565b906103ed565b61080761080160146103f7565b916100d4565b146108cd575b610840918161083a926108286108225f6105a2565b916100d4565b116108a1575b506101008101906103a6565b90610665565b61085f8161085861085261dead6106ae565b9161065b565b141561072c565b61087361086d61deaf610758565b9161065b565b145f146108905761088d6108876001610799565b5b6107b5565b90565b61088d61089c5f61077a565b610888565b5f809133906108ae610084565b90816108b9816105d2565b03925af1506108c6610632565b505f61082e565b8160206109026108fd6108f86108f36108ed6109359860608101906103a6565b90610429565b6104a7565b6104bf565b6104d7565b631bab58f59061092a5f610915306104e3565b9361091e610084565b9889958694859361053a565b83526004830161057a565b03925af1918215610983576108409361083a93610957575b509150915061080d565b6109779060203d811161097c575b61096f8183610511565b81019061054f565b61094d565b503d610965565b61058f565b610990610396565b5060015f5d61099e5f6105a2565b90565b6109aa906104cb565b90565b5f9103126109b757565b61008e565b6109c59061022e565b9052565b91906109dc905f602085019401906109bc565b565b6109e7906109a1565b90630396cb60349290929190803b15610a6557610a175f93610a2295610a0b610084565b9687958694859361053a565b8352600483016109c9565b03925af18015610a6057610a34575b50565b610a53905f3d8111610a59575b610a4b8183610511565b8101906109ad565b5f610a31565b503d610a41565b61058f565b6104ef565b5f7f74657374206661696c0000000000000000000000000000000000000000000000910152565b610a9e60096020926106ca565b610aa781610a6a565b0190565b610ac09060208101905f818303910152610a91565b90565b610acb610084565b62461bcd60e51b815280610ae160048201610aab565b0390fd5b5f1b90565b90610af65f1991610ae5565b9181191691161790565b610b14610b0f610b19926100d4565b6103f4565b6100d4565b90565b90565b90610b34610b2f610b3b92610b00565b610b1c565b8254610aea565b9055565b610b4a906001610b1f565b56fea2646970667358221220b38b9fc26f62a27821d9b7ec4f8d872db3cb781cf35b39974360011b61dcacec64736f6c63430008190033", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "balance": "0xda71b71dbd3438e", + "nonce": "2" + } + }, + "config": { + "chainId": 1337, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "rip7560block": 0, + "rip7712block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "pragueTime": 0, + "terminalTotalDifficulty": 0, + "depositContractAddress": "0x0000000000000000000000000000000000000000", + "blobSchedule": { + "cancun": { + "max": 6, + "target": 3, + "baseFeeUpdateFraction": 3338477 + }, + "prague": { + "max": 9, + "target": 6, + "baseFeeUpdateFraction": 5007716 + } + } + } + }, + "context": { + "number": "88", + "difficulty": "0", + "timestamp": "1738267405", + "gasLimit": "30000000", + "miner": "0x0000000000000000000000000000000000000000", + "baseFeePerGas": "37852" + }, + "input": "0x02f902f3820539028459682f008459697e8a8305fe79940000000071727de22e5e9d8baf0edac6f37da03280b90284765e827f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000008c9d927336adc963536122f8e0d269319e79ed7a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000f4240000000000000000000000000000493e000000000000000000000000000000000000000000000000000000000000493e0000000000000000000000000b2d05e00000000000000000000000000ee6b280000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024a9e966b7000000000000000000000000000000000000000000000000000000000010f4470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002face000000000000000000000000000000000000000000000000000000000000c080a076f549a86d5973384cf79cabbcf2d9ab0ae3478e8d4b5c643d1e45ea9a57af51a052dd4f3bc56de5c971dbcad1dc5d3ea3a6e7fc037cfb9447ce4a73a12db7430d", + "result": { + "accessedSlots": { + "reads": { + "0x0000000000000000000000000000000000000000000000000000000000000002": [ + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "0x83d2064309e31181791f895d99cc244865c480f99200cd4d4f2412a7a3a265b6": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "0xe18cacf0f1fc038f916461d29104232bd93d822359dfc137927858cc71f1e4ed": [ + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ] + }, + "transientReads": {}, + "transientWrites": {}, + "writes": { + "0x0000000000000000000000000000000000000000000000000000000000000002": 2, + "0x83d2064309e31181791f895d99cc244865c480f99200cd4d4f2412a7a3a265b6": 1, + "0xe18cacf0f1fc038f916461d29104232bd93d822359dfc137927858cc71f1e4ed": 1 + } + }, + "calls": [ + { + "accessedSlots": { + "reads": {}, + "transientReads": {}, + "transientWrites": {}, + "writes": {} + }, + "contractSize": {}, + "extCodeAccessInfo": [], + "from": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "gas": "0x54dda", + "gasUsed": "0x8ec", + "input": "0x19822f7c000000000000000000000000000000000000000000000000000000000000006088a9b2626e43da02f978ae6cc89feffb68afcd5860cb9239337352db4b694fe100000000000000000000000000000000000000000000000000000000000000000000000000000000000000008c9d927336adc963536122f8e0d269319e79ed7a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000f4240000000000000000000000000000493e000000000000000000000000000000000000000000000000000000000000493e0000000000000000000000000b2d05e00000000000000000000000000ee6b280000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024a9e966b7000000000000000000000000000000000000000000000000000000000010f4470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002face000000000000000000000000000000000000000000000000000000000000", + "outOfGas": false, + "output": "0x0000000000000000000000000000000000000000000000000000000000000000", + "to": "0x8c9d927336adc963536122f8e0d269319e79ed7a", + "type": "CALL", + "usedOpcodes": {"0x34":1, "0x35":9, "0x36":6, "0x51":1, "0x52":2, "0x56":102, "0x57":19, "0x5b":108, "0xf3":1}, + "value": "0x0" + }, + { + "accessedSlots": { + "reads": { + "0xe18cacf0f1fc038f916461d29104232bd93d822359dfc137927858cc71f1e4ed": [ + "0x0000000000000000000000000000000000000000000000001baab0a330380000" + ] + }, + "transientReads": {}, + "transientWrites": {}, + "writes": { + "0xe18cacf0f1fc038f916461d29104232bd93d822359dfc137927858cc71f1e4ed": 1 + } + }, + "calls": [ + { + "accessedSlots": { + "reads": { + "0x0000000000000000000000000000000000000000000000000000000000000001": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + "transientReads": {}, + "transientWrites": {}, + "writes": { + "0x0000000000000000000000000000000000000000000000000000000000000001": 1 + } + }, + "contractSize": {}, + "extCodeAccessInfo": [], + "from": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "gas": "0x493e0", + "gasUsed": "0x5956", + "input": "0xa9e966b7000000000000000000000000000000000000000000000000000000000010f447", + "outOfGas": false, + "to": "0x8c9d927336adc963536122f8e0d269319e79ed7a", + "type": "CALL", + "usedOpcodes": {"0x34":1, "0x35":2, "0x36":2, "0x51":1, "0x52":1, "0x54":1, "0x55":1, "0x56":33, "0x57":9, "0x5b":35, "0xf3":1}, + "value": "0x0" + } + ], + "contractSize": { + "0x8c9d927336adc963536122f8e0d269319e79ed7a": { + "contractSize": 2946, + "opcode": 241 + } + }, + "extCodeAccessInfo": [], + "from": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "gas": "0x4d7ac", + "gasUsed": "0x6ff7", + "input": "0x0042dc5300000000000000000000000000000000000000000000000000000000000002000000000000000000000000008c9d927336adc963536122f8e0d269319e79ed7a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000000493e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000493e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ee6b280000000000000000000000000000000000000000000000000000000000b2d05e0088a9b2626e43da02f978ae6cc89feffb68afcd5860cb9239337352db4b694fe10000000000000000000000000000000000000000000000000016bcc41e900000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000522d600000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000024a9e966b7000000000000000000000000000000000000000000000000000000000010f447000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "outOfGas": false, + "output": "0x000000000000000000000000000000000000000000000000000421bab3f40fbc", + "to": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "type": "CALL", + "usedOpcodes": {"0x20":1, "0x30":1, "0x33":1, "0x34":1, "0x35":19, "0x36":7, "0x37":2, "0x48":1, "0x51":26, "0x52":31, "0x54":1, "0x55":1, "0x56":27, "0x57":33, "0x5a":5, "0x5b":35, "0xa4":1, "0xf1":1, "0xf3":1}, + "value": "0x0" + }, + { + "accessedSlots": { + "reads": {}, + "transientReads": {}, + "transientWrites": {}, + "writes": {} + }, + "contractSize": {}, + "extCodeAccessInfo": [], + "from": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "gas": "0x44ece", + "gasUsed": "0x0", + "input": "0x", + "outOfGas": false, + "to": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "type": "CALL", + "usedOpcodes": {}, + "value": "0x421bab3f40fbc" + } + ], + "contractSize": { + "0x0000000071727de22e5e9d8baf0edac6f37da032": { + "contractSize": 16035, + "opcode": 241 + }, + "0x8c9d927336adc963536122f8e0d269319e79ed7a": { + "contractSize": 2946, + "opcode": 241 + }, + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "contractSize": 0, + "opcode": 241 + } + }, + "extCodeAccessInfo": [], + "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "gas": "0x5fe79", + "gasUsed": "0x19415", + "input": "0x765e827f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000008c9d927336adc963536122f8e0d269319e79ed7a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000f4240000000000000000000000000000493e000000000000000000000000000000000000000000000000000000000000493e0000000000000000000000000b2d05e00000000000000000000000000ee6b280000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024a9e966b7000000000000000000000000000000000000000000000000000000000010f4470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002face000000000000000000000000000000000000000000000000000000000000", + "keccak": [ + "0x", + "0x0000000000000000000000000000000000000000000000000000000000000000916f81e4e1b2122d13f0474f4c323777192f91bb579723004f6f3062b5fedc68", + "0x0000000000000000000000008c9d927336adc963536122f8e0d269319e79ed7a0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000008c9d927336adc963536122f8e0d269319e79ed7a0000000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470ede3d138a3c0ac5537239d818f52c7c86b466472a500982b0e7dff43ab38975d000000000000000000000000000f4240000000000000000000000000000493e000000000000000000000000000000000000000000000000000000000000493e0000000000000000000000000b2d05e00000000000000000000000000ee6b2800c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "0x0000000000000000000000008c9d927336adc963536122f8e0d269319e79ed7a0000000000000000000000000000000000000000000000000000000000000001", + "0xa9e966b7000000000000000000000000000000000000000000000000000000000010f447", + "0xc72bc304a44b01f425579bd71219ccd5676c732ce2aed103da05dc145f00fe340000000000000000000000000000000071727de22e5e9d8baf0edac6f37da0320000000000000000000000000000000000000000000000000000000000000539" + ], + "outOfGas": false, + "to": "0x0000000071727de22e5e9d8baf0edac6f37da032", + "type": "CALL", + "usedOpcodes": {"0x0":1, "0x20":9, "0x30":2, "0x34":1, "0x35":43, "0x36":24, "0x37":8, "0x38":2, "0x3d":2, "0x46":1, "0x51":56, "0x52":104, "0x54":4, "0x55":4, "0x56":92, "0x57":101, "0x5a":4, "0x5b":116, "0xa1":1, "0xf1":3}, + "value": "0x0" + } +} \ No newline at end of file diff --git a/eth/tracers/native/erc7562.go b/eth/tracers/native/erc7562.go new file mode 100644 index 0000000000..3ab98c7132 --- /dev/null +++ b/eth/tracers/native/erc7562.go @@ -0,0 +1,530 @@ +// Copyright 2025 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 . + +package native + +import ( + "bytes" + "encoding/json" + "errors" + "math/big" + "slices" + "sync/atomic" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/eth/tracers/internal" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" +) + +//go:generate go run github.com/fjl/gencodec -type callFrameWithOpcodes -field-override callFrameWithOpcodesMarshaling -out gen_callframewithopcodes_json.go + +func init() { + tracers.DefaultDirectory.Register("erc7562Tracer", newErc7562Tracer, false) +} + +type contractSizeWithOpcode struct { + ContractSize int `json:"contractSize"` + Opcode vm.OpCode `json:"opcode"` +} + +type callFrameWithOpcodes struct { + Type vm.OpCode `json:"-"` + From common.Address `json:"from"` + Gas uint64 `json:"gas"` + GasUsed uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input []byte `json:"input" rlp:"optional"` + Output []byte `json:"output,omitempty" rlp:"optional"` + Error string `json:"error,omitempty" rlp:"optional"` + RevertReason string `json:"revertReason,omitempty"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Value *big.Int `json:"value,omitempty" rlp:"optional"` + revertedSnapshot bool + + AccessedSlots accessedSlots `json:"accessedSlots"` + ExtCodeAccessInfo []common.Address `json:"extCodeAccessInfo"` + UsedOpcodes map[vm.OpCode]uint64 `json:"usedOpcodes"` + ContractSize map[common.Address]*contractSizeWithOpcode `json:"contractSize"` + OutOfGas bool `json:"outOfGas"` + // Keccak preimages for the whole transaction are stored in the + // root call frame. + KeccakPreimages [][]byte `json:"keccak,omitempty"` + Calls []callFrameWithOpcodes `json:"calls,omitempty" rlp:"optional"` +} + +func (f callFrameWithOpcodes) TypeString() string { + return f.Type.String() +} + +func (f callFrameWithOpcodes) failed() bool { + return len(f.Error) > 0 && f.revertedSnapshot +} + +func (f *callFrameWithOpcodes) processOutput(output []byte, err error, reverted bool) { + output = common.CopyBytes(output) + // Clear error if tx wasn't reverted. This happened + // for pre-homestead contract storage OOG. + if err != nil && !reverted { + err = nil + } + if err == nil { + f.Output = output + return + } + f.Error = err.Error() + f.revertedSnapshot = reverted + if f.Type == vm.CREATE || f.Type == vm.CREATE2 { + f.To = nil + } + if !errors.Is(err, vm.ErrExecutionReverted) || len(output) == 0 { + return + } + f.Output = output + if len(output) < 4 { + return + } + if unpacked, err := abi.UnpackRevert(output); err == nil { + f.RevertReason = unpacked + } +} + +type callFrameWithOpcodesMarshaling struct { + TypeString string `json:"type"` + Gas hexutil.Uint64 + GasUsed hexutil.Uint64 + Value *hexutil.Big + Input hexutil.Bytes + Output hexutil.Bytes + UsedOpcodes map[hexutil.Uint64]uint64 + KeccakPreimages []hexutil.Bytes +} + +type accessedSlots struct { + Reads map[common.Hash][]common.Hash `json:"reads"` + Writes map[common.Hash]uint64 `json:"writes"` + TransientReads map[common.Hash]uint64 `json:"transientReads"` + TransientWrites map[common.Hash]uint64 `json:"transientWrites"` +} + +type opcodeWithPartialStack struct { + Opcode vm.OpCode + StackTopItems []uint256.Int +} + +type erc7562Tracer struct { + config erc7562TracerConfig + gasLimit uint64 + interrupt atomic.Bool // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption + env *tracing.VMContext + + ignoredOpcodes map[vm.OpCode]struct{} + callstackWithOpcodes []callFrameWithOpcodes + lastOpWithStack *opcodeWithPartialStack + keccakPreimages map[string]struct{} +} + +// newErc7562Tracer returns a native go tracer which tracks +// call frames of a tx, and implements vm.EVMLogger. +func newErc7562Tracer(ctx *tracers.Context, cfg json.RawMessage, _ *params.ChainConfig) (*tracers.Tracer, error) { + t, err := newErc7562TracerObject(cfg) + if err != nil { + return nil, err + } + return &tracers.Tracer{ + Hooks: &tracing.Hooks{ + OnTxStart: t.OnTxStart, + OnOpcode: t.OnOpcode, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnLog: t.OnLog, + }, + GetResult: t.GetResult, + Stop: t.Stop, + }, nil +} + +type erc7562TracerConfig struct { + StackTopItemsSize int `json:"stackTopItemsSize"` + IgnoredOpcodes []hexutil.Uint64 `json:"ignoredOpcodes"` // Opcodes to ignore during OnOpcode hook execution + WithLog bool `json:"withLog"` // If true, erc7562 tracer will collect event logs +} + +func getFullConfiguration(partial erc7562TracerConfig) erc7562TracerConfig { + config := partial + + if config.IgnoredOpcodes == nil { + config.IgnoredOpcodes = defaultIgnoredOpcodes() + } + if config.StackTopItemsSize == 0 { + config.StackTopItemsSize = 3 + } + + return config +} + +func newErc7562TracerObject(cfg json.RawMessage) (*erc7562Tracer, error) { + var config erc7562TracerConfig + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + fullConfig := getFullConfiguration(config) + // Create a map of ignored opcodes for fast lookup + ignoredOpcodes := make(map[vm.OpCode]struct{}, len(fullConfig.IgnoredOpcodes)) + for _, op := range fullConfig.IgnoredOpcodes { + ignoredOpcodes[vm.OpCode(op)] = struct{}{} + } + // First callframe contains tx context info + // and is populated on start and end. + return &erc7562Tracer{ + callstackWithOpcodes: make([]callFrameWithOpcodes, 0, 1), + config: fullConfig, + keccakPreimages: make(map[string]struct{}), + ignoredOpcodes: ignoredOpcodes, + }, nil +} + +func (t *erc7562Tracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { + t.env = env + t.gasLimit = tx.Gas() +} + +// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *erc7562Tracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + // Skip if tracing was interrupted + if t.interrupt.Load() { + return + } + + toCopy := to + call := callFrameWithOpcodes{ + Type: vm.OpCode(typ), + From: from, + To: &toCopy, + Input: common.CopyBytes(input), + Gas: gas, + Value: value, + AccessedSlots: accessedSlots{ + Reads: map[common.Hash][]common.Hash{}, + Writes: map[common.Hash]uint64{}, + TransientReads: map[common.Hash]uint64{}, + TransientWrites: map[common.Hash]uint64{}, + }, + UsedOpcodes: map[vm.OpCode]uint64{}, + ExtCodeAccessInfo: make([]common.Address, 0), + ContractSize: map[common.Address]*contractSizeWithOpcode{}, + } + if depth == 0 { + call.Gas = t.gasLimit + } + t.callstackWithOpcodes = append(t.callstackWithOpcodes, call) +} + +func (t *erc7562Tracer) captureEnd(output []byte, err error, reverted bool) { + if len(t.callstackWithOpcodes) != 1 { + return + } + t.callstackWithOpcodes[0].processOutput(output, err, reverted) +} + +// OnExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *erc7562Tracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if t.interrupt.Load() { + return + } + if depth == 0 { + t.captureEnd(output, err, reverted) + return + } + + size := len(t.callstackWithOpcodes) + if size <= 1 { + return + } + // Pop call. + call := t.callstackWithOpcodes[size-1] + t.callstackWithOpcodes = t.callstackWithOpcodes[:size-1] + size -= 1 + + if errors.Is(err, vm.ErrCodeStoreOutOfGas) || errors.Is(err, vm.ErrOutOfGas) { + call.OutOfGas = true + } + call.GasUsed = gasUsed + call.processOutput(output, err, reverted) + // Nest call into parent. + t.callstackWithOpcodes[size-1].Calls = append(t.callstackWithOpcodes[size-1].Calls, call) +} + +func (t *erc7562Tracer) OnTxEnd(receipt *types.Receipt, err error) { + if t.interrupt.Load() { + return + } + // Error happened during tx validation. + if err != nil { + return + } + t.callstackWithOpcodes[0].GasUsed = receipt.GasUsed + if t.config.WithLog { + // Logs are not emitted when the call fails + t.clearFailedLogs(&t.callstackWithOpcodes[0], false) + } +} + +func (t *erc7562Tracer) OnLog(log1 *types.Log) { + // Only logs need to be captured via opcode processing + if !t.config.WithLog { + return + } + // Skip if tracing was interrupted + if t.interrupt.Load() { + return + } + l := callLog{ + Address: log1.Address, + Topics: log1.Topics, + Data: log1.Data, + Position: hexutil.Uint(len(t.callstackWithOpcodes[len(t.callstackWithOpcodes)-1].Calls)), + } + t.callstackWithOpcodes[len(t.callstackWithOpcodes)-1].Logs = append(t.callstackWithOpcodes[len(t.callstackWithOpcodes)-1].Logs, l) +} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *erc7562Tracer) GetResult() (json.RawMessage, error) { + if t.interrupt.Load() { + return nil, t.reason + } + if len(t.callstackWithOpcodes) != 1 { + return nil, errors.New("incorrect number of top-level calls") + } + + keccak := make([][]byte, 0, len(t.callstackWithOpcodes[0].KeccakPreimages)) + for k := range t.keccakPreimages { + keccak = append(keccak, []byte(k)) + } + t.callstackWithOpcodes[0].KeccakPreimages = keccak + slices.SortFunc(keccak, func(a, b []byte) int { + return bytes.Compare(a, b) + }) + + enc, err := json.Marshal(t.callstackWithOpcodes[0]) + if err != nil { + return nil, err + } + + return enc, t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *erc7562Tracer) Stop(err error) { + t.reason = err + t.interrupt.Store(true) +} + +// clearFailedLogs clears the logs of a callframe and all its children +// in case of execution failure. +func (t *erc7562Tracer) clearFailedLogs(cf *callFrameWithOpcodes, parentFailed bool) { + failed := cf.failed() || parentFailed + // Clear own logs + if failed { + cf.Logs = nil + } + for i := range cf.Calls { + t.clearFailedLogs(&cf.Calls[i], failed) + } +} + +func (t *erc7562Tracer) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { + if t.interrupt.Load() { + return + } + var ( + opcode = vm.OpCode(op) + opcodeWithStack *opcodeWithPartialStack + stackSize = len(scope.StackData()) + stackLimit = min(stackSize, t.config.StackTopItemsSize) + stackTopItems = make([]uint256.Int, stackLimit) + ) + for i := 0; i < stackLimit; i++ { + stackTopItems[i] = *peepStack(scope.StackData(), i) + } + opcodeWithStack = &opcodeWithPartialStack{ + Opcode: opcode, + StackTopItems: stackTopItems, + } + t.handleReturnRevert(opcode) + size := len(t.callstackWithOpcodes) + currentCallFrame := &t.callstackWithOpcodes[size-1] + if t.lastOpWithStack != nil { + t.handleExtOpcodes(opcode, currentCallFrame) + } + t.handleAccessedContractSize(opcode, scope, currentCallFrame) + if t.lastOpWithStack != nil { + t.handleGasObserved(opcode, currentCallFrame) + } + t.storeUsedOpcode(opcode, currentCallFrame) + t.handleStorageAccess(opcode, scope, currentCallFrame) + t.storeKeccak(opcode, scope) + t.lastOpWithStack = opcodeWithStack +} + +func (t *erc7562Tracer) handleReturnRevert(opcode vm.OpCode) { + if opcode == vm.REVERT || opcode == vm.RETURN { + t.lastOpWithStack = nil + } +} + +func (t *erc7562Tracer) handleGasObserved(opcode vm.OpCode, currentCallFrame *callFrameWithOpcodes) { + // [OP-012] + pendingGasObserved := t.lastOpWithStack.Opcode == vm.GAS && !isCall(opcode) + if pendingGasObserved { + currentCallFrame.UsedOpcodes[vm.GAS]++ + } +} + +func (t *erc7562Tracer) storeUsedOpcode(opcode vm.OpCode, currentCallFrame *callFrameWithOpcodes) { + // ignore "unimportant" opcodes + if opcode != vm.GAS && !t.isIgnoredOpcode(opcode) { + currentCallFrame.UsedOpcodes[opcode]++ + } +} + +func (t *erc7562Tracer) handleStorageAccess(opcode vm.OpCode, scope tracing.OpContext, currentCallFrame *callFrameWithOpcodes) { + if opcode == vm.SLOAD || opcode == vm.SSTORE || opcode == vm.TLOAD || opcode == vm.TSTORE { + slot := common.BytesToHash(peepStack(scope.StackData(), 0).Bytes()) + addr := scope.Address() + + if opcode == vm.SLOAD { + // read slot values before this UserOp was created + // (so saving it if it was written before the first read) + _, rOk := currentCallFrame.AccessedSlots.Reads[slot] + _, wOk := currentCallFrame.AccessedSlots.Writes[slot] + if !rOk && !wOk { + currentCallFrame.AccessedSlots.Reads[slot] = append(currentCallFrame.AccessedSlots.Reads[slot], t.env.StateDB.GetState(addr, slot)) + } + } else if opcode == vm.SSTORE { + currentCallFrame.AccessedSlots.Writes[slot]++ + } else if opcode == vm.TLOAD { + currentCallFrame.AccessedSlots.TransientReads[slot]++ + } else { + currentCallFrame.AccessedSlots.TransientWrites[slot]++ + } + } +} + +func (t *erc7562Tracer) storeKeccak(opcode vm.OpCode, scope tracing.OpContext) { + if opcode == vm.KECCAK256 { + dataOffset := peepStack(scope.StackData(), 0).Uint64() + dataLength := peepStack(scope.StackData(), 1).Uint64() + preimage, err := internal.GetMemoryCopyPadded(scope.MemoryData(), int64(dataOffset), int64(dataLength)) + if err != nil { + log.Warn("erc7562Tracer: failed to copy keccak preimage from memory", "err", err) + return + } + t.keccakPreimages[string(preimage)] = struct{}{} + } +} + +func (t *erc7562Tracer) handleExtOpcodes(opcode vm.OpCode, currentCallFrame *callFrameWithOpcodes) { + if isEXT(t.lastOpWithStack.Opcode) { + addr := common.HexToAddress(t.lastOpWithStack.StackTopItems[0].Hex()) + + // only store the last EXTCODE* opcode per address - could even be a boolean for our current use-case + // [OP-051] + + if !(t.lastOpWithStack.Opcode == vm.EXTCODESIZE && opcode == vm.ISZERO) { + currentCallFrame.ExtCodeAccessInfo = append(currentCallFrame.ExtCodeAccessInfo, addr) + } + } +} + +func (t *erc7562Tracer) handleAccessedContractSize(opcode vm.OpCode, scope tracing.OpContext, currentCallFrame *callFrameWithOpcodes) { + // [OP-041] + if isEXTorCALL(opcode) { + n := 0 + if !isEXT(opcode) { + n = 1 + } + addr := common.BytesToAddress(peepStack(scope.StackData(), n).Bytes()) + if _, ok := currentCallFrame.ContractSize[addr]; !ok { + currentCallFrame.ContractSize[addr] = &contractSizeWithOpcode{ + ContractSize: len(t.env.StateDB.GetCode(addr)), + Opcode: opcode, + } + } + } +} + +func peepStack(stackData []uint256.Int, n int) *uint256.Int { + return &stackData[len(stackData)-n-1] +} + +func isEXTorCALL(opcode vm.OpCode) bool { + return isEXT(opcode) || isCall(opcode) +} + +func isEXT(opcode vm.OpCode) bool { + return opcode == vm.EXTCODEHASH || + opcode == vm.EXTCODESIZE || + opcode == vm.EXTCODECOPY +} + +func isCall(opcode vm.OpCode) bool { + return opcode == vm.CALL || + opcode == vm.CALLCODE || + opcode == vm.DELEGATECALL || + opcode == vm.STATICCALL +} + +// Check if this opcode is ignored for the purposes of generating the used opcodes report +func (t *erc7562Tracer) isIgnoredOpcode(opcode vm.OpCode) bool { + if _, ok := t.ignoredOpcodes[opcode]; ok { + return true + } + return false +} + +func defaultIgnoredOpcodes() []hexutil.Uint64 { + ignored := make([]hexutil.Uint64, 0, 64) + + // Allow all PUSHx, DUPx and SWAPx opcodes as they have sequential codes + for op := vm.PUSH0; op < vm.SWAP16; op++ { + ignored = append(ignored, hexutil.Uint64(op)) + } + + for _, op := range []vm.OpCode{ + vm.POP, vm.ADD, vm.SUB, vm.MUL, + vm.DIV, vm.EQ, vm.LT, vm.GT, + vm.SLT, vm.SGT, vm.SHL, vm.SHR, + vm.AND, vm.OR, vm.NOT, vm.ISZERO, + } { + ignored = append(ignored, hexutil.Uint64(op)) + } + + return ignored +} diff --git a/eth/tracers/native/gen_callframewithopcodes_json.go b/eth/tracers/native/gen_callframewithopcodes_json.go new file mode 100644 index 0000000000..f3d5dde8f1 --- /dev/null +++ b/eth/tracers/native/gen_callframewithopcodes_json.go @@ -0,0 +1,159 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package native + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/vm" +) + +var _ = (*callFrameWithOpcodesMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (c callFrameWithOpcodes) MarshalJSON() ([]byte, error) { + type callFrameWithOpcodes0 struct { + Type vm.OpCode `json:"-"` + From common.Address `json:"from"` + Gas hexutil.Uint64 `json:"gas"` + GasUsed hexutil.Uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input hexutil.Bytes `json:"input" rlp:"optional"` + Output hexutil.Bytes `json:"output,omitempty" rlp:"optional"` + Error string `json:"error,omitempty" rlp:"optional"` + RevertReason string `json:"revertReason,omitempty"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` + AccessedSlots accessedSlots `json:"accessedSlots"` + ExtCodeAccessInfo []common.Address `json:"extCodeAccessInfo"` + UsedOpcodes map[hexutil.Uint64]uint64 `json:"usedOpcodes"` + ContractSize map[common.Address]*contractSizeWithOpcode `json:"contractSize"` + OutOfGas bool `json:"outOfGas"` + KeccakPreimages []hexutil.Bytes `json:"keccak,omitempty"` + Calls []callFrameWithOpcodes `json:"calls,omitempty" rlp:"optional"` + TypeString string `json:"type"` + } + var enc callFrameWithOpcodes0 + enc.Type = c.Type + enc.From = c.From + enc.Gas = hexutil.Uint64(c.Gas) + enc.GasUsed = hexutil.Uint64(c.GasUsed) + enc.To = c.To + enc.Input = c.Input + enc.Output = c.Output + enc.Error = c.Error + enc.RevertReason = c.RevertReason + enc.Logs = c.Logs + enc.Value = (*hexutil.Big)(c.Value) + enc.AccessedSlots = c.AccessedSlots + enc.ExtCodeAccessInfo = c.ExtCodeAccessInfo + if c.UsedOpcodes != nil { + enc.UsedOpcodes = make(map[hexutil.Uint64]uint64, len(c.UsedOpcodes)) + for k, v := range c.UsedOpcodes { + enc.UsedOpcodes[hexutil.Uint64(k)] = v + } + } + enc.ContractSize = c.ContractSize + enc.OutOfGas = c.OutOfGas + if c.KeccakPreimages != nil { + enc.KeccakPreimages = make([]hexutil.Bytes, len(c.KeccakPreimages)) + for k, v := range c.KeccakPreimages { + enc.KeccakPreimages[k] = v + } + } + enc.Calls = c.Calls + enc.TypeString = c.TypeString() + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (c *callFrameWithOpcodes) UnmarshalJSON(input []byte) error { + type callFrameWithOpcodes0 struct { + Type *vm.OpCode `json:"-"` + From *common.Address `json:"from"` + Gas *hexutil.Uint64 `json:"gas"` + GasUsed *hexutil.Uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input *hexutil.Bytes `json:"input" rlp:"optional"` + Output *hexutil.Bytes `json:"output,omitempty" rlp:"optional"` + Error *string `json:"error,omitempty" rlp:"optional"` + RevertReason *string `json:"revertReason,omitempty"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` + AccessedSlots *accessedSlots `json:"accessedSlots"` + ExtCodeAccessInfo []common.Address `json:"extCodeAccessInfo"` + UsedOpcodes map[hexutil.Uint64]uint64 `json:"usedOpcodes"` + ContractSize map[common.Address]*contractSizeWithOpcode `json:"contractSize"` + OutOfGas *bool `json:"outOfGas"` + KeccakPreimages []hexutil.Bytes `json:"keccak,omitempty"` + Calls []callFrameWithOpcodes `json:"calls,omitempty" rlp:"optional"` + } + var dec callFrameWithOpcodes0 + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Type != nil { + c.Type = *dec.Type + } + if dec.From != nil { + c.From = *dec.From + } + if dec.Gas != nil { + c.Gas = uint64(*dec.Gas) + } + if dec.GasUsed != nil { + c.GasUsed = uint64(*dec.GasUsed) + } + if dec.To != nil { + c.To = dec.To + } + if dec.Input != nil { + c.Input = *dec.Input + } + if dec.Output != nil { + c.Output = *dec.Output + } + if dec.Error != nil { + c.Error = *dec.Error + } + if dec.RevertReason != nil { + c.RevertReason = *dec.RevertReason + } + if dec.Logs != nil { + c.Logs = dec.Logs + } + if dec.Value != nil { + c.Value = (*big.Int)(dec.Value) + } + if dec.AccessedSlots != nil { + c.AccessedSlots = *dec.AccessedSlots + } + if dec.ExtCodeAccessInfo != nil { + c.ExtCodeAccessInfo = dec.ExtCodeAccessInfo + } + if dec.UsedOpcodes != nil { + c.UsedOpcodes = make(map[vm.OpCode]uint64, len(dec.UsedOpcodes)) + for k, v := range dec.UsedOpcodes { + c.UsedOpcodes[vm.OpCode(k)] = v + } + } + if dec.ContractSize != nil { + c.ContractSize = dec.ContractSize + } + if dec.OutOfGas != nil { + c.OutOfGas = *dec.OutOfGas + } + if dec.KeccakPreimages != nil { + c.KeccakPreimages = make([][]byte, len(dec.KeccakPreimages)) + for k, v := range dec.KeccakPreimages { + c.KeccakPreimages[k] = v + } + } + if dec.Calls != nil { + c.Calls = dec.Calls + } + return nil +} From 63740b7aca732f6c204c56a9e4b4932f5251e4e0 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 20 May 2025 18:31:01 +0200 Subject: [PATCH 041/365] core/state: reduce allocation in updateStateObject (#31861) Optimize updateStateObject to reduce an allocation. --- core/state/statedb.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 2453d67f3e..51453055c3 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -562,9 +562,8 @@ func (s *StateDB) GetTransientState(addr common.Address, key common.Hash) common // updateStateObject writes the given object to the trie. func (s *StateDB) updateStateObject(obj *stateObject) { // Encode the account and update the account trie - addr := obj.Address() - if err := s.trie.UpdateAccount(addr, &obj.data, len(obj.code)); err != nil { - s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err)) + if err := s.trie.UpdateAccount(obj.Address(), &obj.data, len(obj.code)); err != nil { + s.setError(fmt.Errorf("updateStateObject (%x) error: %v", obj.Address(), err)) } if obj.dirtyCode { s.trie.UpdateContractCode(obj.Address(), common.BytesToHash(obj.CodeHash()), obj.code) From a4959685a2ca2eba558ac9c233c4b67c9fd0edac Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Wed, 21 May 2025 11:53:29 +0200 Subject: [PATCH 042/365] eth/catalyst: move witness methods from engine api (#31867) No functional changes, just moves the witness methods into its own file --- eth/catalyst/api.go | 265 ------------------------------------ eth/catalyst/witness.go | 295 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+), 265 deletions(-) create mode 100644 eth/catalyst/witness.go diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index be25712c97..b5f035b6d2 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -27,11 +27,8 @@ import ( "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/stateless" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/version" @@ -245,58 +242,6 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa return api.forkchoiceUpdated(update, params, engine.PayloadV3, false) } -// ForkchoiceUpdatedWithWitnessV1 is analogous to ForkchoiceUpdatedV1, only it -// generates an execution witness too if block building was requested. -func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { - if payloadAttributes != nil { - switch { - case payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil: - return engine.STATUS_INVALID, paramsErr("withdrawals and beacon root not supported in V1") - case !api.checkFork(payloadAttributes.Timestamp, forks.Paris, forks.Shanghai): - return engine.STATUS_INVALID, paramsErr("fcuV1 called post-shanghai") - } - } - return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, true) -} - -// ForkchoiceUpdatedWithWitnessV2 is analogous to ForkchoiceUpdatedV2, only it -// generates an execution witness too if block building was requested. -func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { - if params != nil { - switch { - case params.BeaconRoot != nil: - return engine.STATUS_INVALID, attributesErr("unexpected beacon root") - case api.checkFork(params.Timestamp, forks.Paris) && params.Withdrawals != nil: - return engine.STATUS_INVALID, attributesErr("withdrawals before shanghai") - case api.checkFork(params.Timestamp, forks.Shanghai) && params.Withdrawals == nil: - return engine.STATUS_INVALID, attributesErr("missing withdrawals") - case !api.checkFork(params.Timestamp, forks.Paris, forks.Shanghai): - return engine.STATUS_INVALID, unsupportedForkErr("fcuV2 must only be called with paris or shanghai payloads") - } - } - return api.forkchoiceUpdated(update, params, engine.PayloadV2, true) -} - -// ForkchoiceUpdatedWithWitnessV3 is analogous to ForkchoiceUpdatedV3, only it -// generates an execution witness too if block building was requested. -func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { - if params != nil { - switch { - case params.Withdrawals == nil: - return engine.STATUS_INVALID, attributesErr("missing withdrawals") - case params.BeaconRoot == nil: - return engine.STATUS_INVALID, attributesErr("missing beacon root") - case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague): - return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads") - } - } - // TODO(matt): the spec requires that fcu is applied when called on a valid - // hash, even if params are wrong. To do this we need to split up - // forkchoiceUpdate into a function that only updates the head and then a - // function that kicks off block construction. - return api.forkchoiceUpdated(update, params, engine.PayloadV3, true) -} - func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, payloadWitness bool) (engine.ForkChoiceResponse, error) { api.forkchoiceLock.Lock() defer api.forkchoiceLock.Unlock() @@ -615,160 +560,6 @@ func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHas return api.newPayload(params, versionedHashes, beaconRoot, requests, false) } -// NewPayloadWithWitnessV1 is analogous to NewPayloadV1, only it also generates -// and returns a stateless witness after running the payload. -func (api *ConsensusAPI) NewPayloadWithWitnessV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - if params.Withdrawals != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) - } - return api.newPayload(params, nil, nil, nil, true) -} - -// NewPayloadWithWitnessV2 is analogous to NewPayloadV2, only it also generates -// and returns a stateless witness after running the payload. -func (api *ConsensusAPI) NewPayloadWithWitnessV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - var ( - cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp) - shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp) - ) - switch { - case cancun: - return invalidStatus, paramsErr("can't use newPayloadV2 post-cancun") - case shanghai && params.Withdrawals == nil: - return invalidStatus, paramsErr("nil withdrawals post-shanghai") - case !shanghai && params.Withdrawals != nil: - return invalidStatus, paramsErr("non-nil withdrawals pre-shanghai") - case params.ExcessBlobGas != nil: - return invalidStatus, paramsErr("non-nil excessBlobGas pre-cancun") - case params.BlobGasUsed != nil: - return invalidStatus, paramsErr("non-nil blobGasUsed pre-cancun") - } - return api.newPayload(params, nil, nil, nil, true) -} - -// NewPayloadWithWitnessV3 is analogous to NewPayloadV3, only it also generates -// and returns a stateless witness after running the payload. -func (api *ConsensusAPI) NewPayloadWithWitnessV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { - switch { - case params.Withdrawals == nil: - return invalidStatus, paramsErr("nil withdrawals post-shanghai") - case params.ExcessBlobGas == nil: - return invalidStatus, paramsErr("nil excessBlobGas post-cancun") - case params.BlobGasUsed == nil: - return invalidStatus, paramsErr("nil blobGasUsed post-cancun") - case versionedHashes == nil: - return invalidStatus, paramsErr("nil versionedHashes post-cancun") - case beaconRoot == nil: - return invalidStatus, paramsErr("nil beaconRoot post-cancun") - case !api.checkFork(params.Timestamp, forks.Cancun): - return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") - } - return api.newPayload(params, versionedHashes, beaconRoot, nil, true) -} - -// NewPayloadWithWitnessV4 is analogous to NewPayloadV4, only it also generates -// and returns a stateless witness after running the payload. -func (api *ConsensusAPI) NewPayloadWithWitnessV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) { - switch { - case params.Withdrawals == nil: - return invalidStatus, paramsErr("nil withdrawals post-shanghai") - case params.ExcessBlobGas == nil: - return invalidStatus, paramsErr("nil excessBlobGas post-cancun") - case params.BlobGasUsed == nil: - return invalidStatus, paramsErr("nil blobGasUsed post-cancun") - case versionedHashes == nil: - return invalidStatus, paramsErr("nil versionedHashes post-cancun") - case beaconRoot == nil: - return invalidStatus, paramsErr("nil beaconRoot post-cancun") - case executionRequests == nil: - return invalidStatus, paramsErr("nil executionRequests post-prague") - case !api.checkFork(params.Timestamp, forks.Prague): - return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") - } - requests := convertRequests(executionRequests) - if err := validateRequests(requests); err != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err) - } - return api.newPayload(params, versionedHashes, beaconRoot, requests, true) -} - -// ExecuteStatelessPayloadV1 is analogous to NewPayloadV1, only it operates in -// a stateless mode on top of a provided witness instead of the local database. -func (api *ConsensusAPI) ExecuteStatelessPayloadV1(params engine.ExecutableData, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - if params.Withdrawals != nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) - } - return api.executeStatelessPayload(params, nil, nil, nil, opaqueWitness) -} - -// ExecuteStatelessPayloadV2 is analogous to NewPayloadV2, only it operates in -// a stateless mode on top of a provided witness instead of the local database. -func (api *ConsensusAPI) ExecuteStatelessPayloadV2(params engine.ExecutableData, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - var ( - cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp) - shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp) - ) - switch { - case cancun: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("can't use newPayloadV2 post-cancun") - case shanghai && params.Withdrawals == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") - case !shanghai && params.Withdrawals != nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil withdrawals pre-shanghai") - case params.ExcessBlobGas != nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil excessBlobGas pre-cancun") - case params.BlobGasUsed != nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil blobGasUsed pre-cancun") - } - return api.executeStatelessPayload(params, nil, nil, nil, opaqueWitness) -} - -// ExecuteStatelessPayloadV3 is analogous to NewPayloadV3, only it operates in -// a stateless mode on top of a provided witness instead of the local database. -func (api *ConsensusAPI) ExecuteStatelessPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - switch { - case params.Withdrawals == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") - case params.ExcessBlobGas == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun") - case params.BlobGasUsed == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun") - case versionedHashes == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun") - case beaconRoot == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun") - case !api.checkFork(params.Timestamp, forks.Cancun): - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") - } - return api.executeStatelessPayload(params, versionedHashes, beaconRoot, nil, opaqueWitness) -} - -// ExecuteStatelessPayloadV4 is analogous to NewPayloadV4, only it operates in -// a stateless mode on top of a provided witness instead of the local database. -func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - switch { - case params.Withdrawals == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") - case params.ExcessBlobGas == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun") - case params.BlobGasUsed == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun") - case versionedHashes == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun") - case beaconRoot == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun") - case executionRequests == nil: - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague") - case !api.checkFork(params.Timestamp, forks.Prague): - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") - } - requests := convertRequests(executionRequests) - if err := validateRequests(requests); err != nil { - return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err) - } - return api.executeStatelessPayload(params, versionedHashes, beaconRoot, requests, opaqueWitness) -} - func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, witness bool) (engine.PayloadStatusV1, error) { // The locking here is, strictly, not required. Without these locks, this can happen: // @@ -884,62 +675,6 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe return engine.PayloadStatusV1{Status: engine.VALID, Witness: ow, LatestValidHash: &hash}, nil } -func (api *ConsensusAPI) executeStatelessPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { - log.Trace("Engine API request received", "method", "ExecuteStatelessPayload", "number", params.Number, "hash", params.BlockHash) - block, err := engine.ExecutableDataToBlockNoHash(params, versionedHashes, beaconRoot, requests) - if err != nil { - bgu := "nil" - if params.BlobGasUsed != nil { - bgu = strconv.Itoa(int(*params.BlobGasUsed)) - } - ebg := "nil" - if params.ExcessBlobGas != nil { - ebg = strconv.Itoa(int(*params.ExcessBlobGas)) - } - log.Warn("Invalid ExecuteStatelessPayload params", - "params.Number", params.Number, - "params.ParentHash", params.ParentHash, - "params.BlockHash", params.BlockHash, - "params.StateRoot", params.StateRoot, - "params.FeeRecipient", params.FeeRecipient, - "params.LogsBloom", common.PrettyBytes(params.LogsBloom), - "params.Random", params.Random, - "params.GasLimit", params.GasLimit, - "params.GasUsed", params.GasUsed, - "params.Timestamp", params.Timestamp, - "params.ExtraData", common.PrettyBytes(params.ExtraData), - "params.BaseFeePerGas", params.BaseFeePerGas, - "params.BlobGasUsed", bgu, - "params.ExcessBlobGas", ebg, - "len(params.Transactions)", len(params.Transactions), - "len(params.Withdrawals)", len(params.Withdrawals), - "beaconRoot", beaconRoot, - "len(requests)", len(requests), - "error", err) - errorMsg := err.Error() - return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil - } - witness := new(stateless.Witness) - if err := rlp.DecodeBytes(opaqueWitness, witness); err != nil { - log.Warn("Invalid ExecuteStatelessPayload witness", "err", err) - errorMsg := err.Error() - return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil - } - // Stash away the last update to warn the user if the beacon client goes offline - api.lastNewPayloadLock.Lock() - api.lastNewPayloadUpdate = time.Now() - api.lastNewPayloadLock.Unlock() - - log.Trace("Executing block statelessly", "number", block.Number(), "hash", params.BlockHash) - stateRoot, receiptRoot, err := core.ExecuteStateless(api.config(), vm.Config{}, block, witness) - if err != nil { - log.Warn("ExecuteStatelessPayload: execution failed", "err", err) - errorMsg := err.Error() - return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil - } - return engine.StatelessPayloadStatusV1{Status: engine.VALID, StateRoot: stateRoot, ReceiptsRoot: receiptRoot}, nil -} - // delayPayloadImport stashes the given block away for import at a later time, // either via a forkchoice update or a sync extension. This method is meant to // be called by the newpayload command when the block seems to be ok, but some diff --git a/eth/catalyst/witness.go b/eth/catalyst/witness.go new file mode 100644 index 0000000000..214bee57a4 --- /dev/null +++ b/eth/catalyst/witness.go @@ -0,0 +1,295 @@ +// Copyright 2025 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 . + +package catalyst + +import ( + "errors" + "strconv" + "time" + + "github.com/ethereum/go-ethereum/beacon/engine" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/stateless" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params/forks" + "github.com/ethereum/go-ethereum/rlp" +) + +// ForkchoiceUpdatedWithWitnessV1 is analogous to ForkchoiceUpdatedV1, only it +// generates an execution witness too if block building was requested. +func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { + if payloadAttributes != nil { + switch { + case payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil: + return engine.STATUS_INVALID, paramsErr("withdrawals and beacon root not supported in V1") + case !api.checkFork(payloadAttributes.Timestamp, forks.Paris, forks.Shanghai): + return engine.STATUS_INVALID, paramsErr("fcuV1 called post-shanghai") + } + } + return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, true) +} + +// ForkchoiceUpdatedWithWitnessV2 is analogous to ForkchoiceUpdatedV2, only it +// generates an execution witness too if block building was requested. +func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { + if params != nil { + switch { + case params.BeaconRoot != nil: + return engine.STATUS_INVALID, attributesErr("unexpected beacon root") + case api.checkFork(params.Timestamp, forks.Paris) && params.Withdrawals != nil: + return engine.STATUS_INVALID, attributesErr("withdrawals before shanghai") + case api.checkFork(params.Timestamp, forks.Shanghai) && params.Withdrawals == nil: + return engine.STATUS_INVALID, attributesErr("missing withdrawals") + case !api.checkFork(params.Timestamp, forks.Paris, forks.Shanghai): + return engine.STATUS_INVALID, unsupportedForkErr("fcuV2 must only be called with paris or shanghai payloads") + } + } + return api.forkchoiceUpdated(update, params, engine.PayloadV2, true) +} + +// ForkchoiceUpdatedWithWitnessV3 is analogous to ForkchoiceUpdatedV3, only it +// generates an execution witness too if block building was requested. +func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { + if params != nil { + switch { + case params.Withdrawals == nil: + return engine.STATUS_INVALID, attributesErr("missing withdrawals") + case params.BeaconRoot == nil: + return engine.STATUS_INVALID, attributesErr("missing beacon root") + case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague): + return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads") + } + } + // TODO(matt): the spec requires that fcu is applied when called on a valid + // hash, even if params are wrong. To do this we need to split up + // forkchoiceUpdate into a function that only updates the head and then a + // function that kicks off block construction. + return api.forkchoiceUpdated(update, params, engine.PayloadV3, true) +} + +// NewPayloadWithWitnessV1 is analogous to NewPayloadV1, only it also generates +// and returns a stateless witness after running the payload. +func (api *ConsensusAPI) NewPayloadWithWitnessV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) { + if params.Withdrawals != nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) + } + return api.newPayload(params, nil, nil, nil, true) +} + +// NewPayloadWithWitnessV2 is analogous to NewPayloadV2, only it also generates +// and returns a stateless witness after running the payload. +func (api *ConsensusAPI) NewPayloadWithWitnessV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { + var ( + cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp) + shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp) + ) + switch { + case cancun: + return invalidStatus, paramsErr("can't use newPayloadV2 post-cancun") + case shanghai && params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case !shanghai && params.Withdrawals != nil: + return invalidStatus, paramsErr("non-nil withdrawals pre-shanghai") + case params.ExcessBlobGas != nil: + return invalidStatus, paramsErr("non-nil excessBlobGas pre-cancun") + case params.BlobGasUsed != nil: + return invalidStatus, paramsErr("non-nil blobGasUsed pre-cancun") + } + return api.newPayload(params, nil, nil, nil, true) +} + +// NewPayloadWithWitnessV3 is analogous to NewPayloadV3, only it also generates +// and returns a stateless witness after running the payload. +func (api *ConsensusAPI) NewPayloadWithWitnessV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { + switch { + case params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return invalidStatus, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return invalidStatus, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return invalidStatus, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return invalidStatus, paramsErr("nil beaconRoot post-cancun") + case !api.checkFork(params.Timestamp, forks.Cancun): + return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") + } + return api.newPayload(params, versionedHashes, beaconRoot, nil, true) +} + +// NewPayloadWithWitnessV4 is analogous to NewPayloadV4, only it also generates +// and returns a stateless witness after running the payload. +func (api *ConsensusAPI) NewPayloadWithWitnessV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) { + switch { + case params.Withdrawals == nil: + return invalidStatus, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return invalidStatus, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return invalidStatus, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return invalidStatus, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return invalidStatus, paramsErr("nil beaconRoot post-cancun") + case executionRequests == nil: + return invalidStatus, paramsErr("nil executionRequests post-prague") + case !api.checkFork(params.Timestamp, forks.Prague): + return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") + } + requests := convertRequests(executionRequests) + if err := validateRequests(requests); err != nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err) + } + return api.newPayload(params, versionedHashes, beaconRoot, requests, true) +} + +// ExecuteStatelessPayloadV1 is analogous to NewPayloadV1, only it operates in +// a stateless mode on top of a provided witness instead of the local database. +func (api *ConsensusAPI) ExecuteStatelessPayloadV1(params engine.ExecutableData, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { + if params.Withdrawals != nil { + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) + } + return api.executeStatelessPayload(params, nil, nil, nil, opaqueWitness) +} + +// ExecuteStatelessPayloadV2 is analogous to NewPayloadV2, only it operates in +// a stateless mode on top of a provided witness instead of the local database. +func (api *ConsensusAPI) ExecuteStatelessPayloadV2(params engine.ExecutableData, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { + var ( + cancun = api.config().IsCancun(api.config().LondonBlock, params.Timestamp) + shanghai = api.config().IsShanghai(api.config().LondonBlock, params.Timestamp) + ) + switch { + case cancun: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("can't use newPayloadV2 post-cancun") + case shanghai && params.Withdrawals == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") + case !shanghai && params.Withdrawals != nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil withdrawals pre-shanghai") + case params.ExcessBlobGas != nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil excessBlobGas pre-cancun") + case params.BlobGasUsed != nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("non-nil blobGasUsed pre-cancun") + } + return api.executeStatelessPayload(params, nil, nil, nil, opaqueWitness) +} + +// ExecuteStatelessPayloadV3 is analogous to NewPayloadV3, only it operates in +// a stateless mode on top of a provided witness instead of the local database. +func (api *ConsensusAPI) ExecuteStatelessPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { + switch { + case params.Withdrawals == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun") + case !api.checkFork(params.Timestamp, forks.Cancun): + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") + } + return api.executeStatelessPayload(params, versionedHashes, beaconRoot, nil, opaqueWitness) +} + +// ExecuteStatelessPayloadV4 is analogous to NewPayloadV4, only it operates in +// a stateless mode on top of a provided witness instead of the local database. +func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { + switch { + case params.Withdrawals == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil withdrawals post-shanghai") + case params.ExcessBlobGas == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil excessBlobGas post-cancun") + case params.BlobGasUsed == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil blobGasUsed post-cancun") + case versionedHashes == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil versionedHashes post-cancun") + case beaconRoot == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun") + case executionRequests == nil: + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague") + case !api.checkFork(params.Timestamp, forks.Prague): + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") + } + requests := convertRequests(executionRequests) + if err := validateRequests(requests); err != nil { + return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err) + } + return api.executeStatelessPayload(params, versionedHashes, beaconRoot, requests, opaqueWitness) +} + +func (api *ConsensusAPI) executeStatelessPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, opaqueWitness hexutil.Bytes) (engine.StatelessPayloadStatusV1, error) { + log.Trace("Engine API request received", "method", "ExecuteStatelessPayload", "number", params.Number, "hash", params.BlockHash) + block, err := engine.ExecutableDataToBlockNoHash(params, versionedHashes, beaconRoot, requests) + if err != nil { + bgu := "nil" + if params.BlobGasUsed != nil { + bgu = strconv.Itoa(int(*params.BlobGasUsed)) + } + ebg := "nil" + if params.ExcessBlobGas != nil { + ebg = strconv.Itoa(int(*params.ExcessBlobGas)) + } + log.Warn("Invalid ExecuteStatelessPayload params", + "params.Number", params.Number, + "params.ParentHash", params.ParentHash, + "params.BlockHash", params.BlockHash, + "params.StateRoot", params.StateRoot, + "params.FeeRecipient", params.FeeRecipient, + "params.LogsBloom", common.PrettyBytes(params.LogsBloom), + "params.Random", params.Random, + "params.GasLimit", params.GasLimit, + "params.GasUsed", params.GasUsed, + "params.Timestamp", params.Timestamp, + "params.ExtraData", common.PrettyBytes(params.ExtraData), + "params.BaseFeePerGas", params.BaseFeePerGas, + "params.BlobGasUsed", bgu, + "params.ExcessBlobGas", ebg, + "len(params.Transactions)", len(params.Transactions), + "len(params.Withdrawals)", len(params.Withdrawals), + "beaconRoot", beaconRoot, + "len(requests)", len(requests), + "error", err) + errorMsg := err.Error() + return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil + } + witness := new(stateless.Witness) + if err := rlp.DecodeBytes(opaqueWitness, witness); err != nil { + log.Warn("Invalid ExecuteStatelessPayload witness", "err", err) + errorMsg := err.Error() + return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil + } + // Stash away the last update to warn the user if the beacon client goes offline + api.lastNewPayloadLock.Lock() + api.lastNewPayloadUpdate = time.Now() + api.lastNewPayloadLock.Unlock() + + log.Trace("Executing block statelessly", "number", block.Number(), "hash", params.BlockHash) + stateRoot, receiptRoot, err := core.ExecuteStateless(api.config(), vm.Config{}, block, witness) + if err != nil { + log.Warn("ExecuteStatelessPayload: execution failed", "err", err) + errorMsg := err.Error() + return engine.StatelessPayloadStatusV1{Status: engine.INVALID, ValidationError: &errorMsg}, nil + } + return engine.StatelessPayloadStatusV1{Status: engine.VALID, StateRoot: stateRoot, ReceiptsRoot: receiptRoot}, nil +} From 0287666b7d9beffb93f5a7c6500d242d00dbd085 Mon Sep 17 00:00:00 2001 From: wellna Date: Wed, 21 May 2025 13:20:36 +0100 Subject: [PATCH 043/365] eth/tracers: Improve test coverage for toWord (#31846) --- eth/tracers/js/goja.go | 1 - eth/tracers/js/tracer_test.go | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index d1e65bf7f4..7ec737f4e4 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -480,7 +480,6 @@ func (t *jsTracer) setBuiltinFunctions() { return hexutil.Encode(b) }) vm.Set("toWord", func(v goja.Value) goja.Value { - // TODO: add test with []byte len < 32 or > 32 b, err := t.fromBuf(vm, v, true) if err != nil { vm.Interrupt(err) diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go index dbfc7308f7..a12b990a93 100644 --- a/eth/tracers/js/tracer_test.go +++ b/eth/tracers/js/tracer_test.go @@ -122,9 +122,15 @@ func TestTracer(t *testing.T) { }, { // tests gasUsed code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed; }}", want: `"100000.21006"`, - }, { + }, { // tests toWord with byte array length < 32 code: "{res: null, step: function(log) {}, fault: function() {}, result: function() { return toWord('0xffaa') }}", want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":255,"31":170}`, + }, { // tests toWord with byte array length = 32 + code: "{step: function() {}, fault: function() {}, result: function() { return toWord('0x1234567890123456789012345678901234567890123456789012345678901234'); }}", + want: `{"0":18,"1":52,"2":86,"3":120,"4":144,"5":18,"6":52,"7":86,"8":120,"9":144,"10":18,"11":52,"12":86,"13":120,"14":144,"15":18,"16":52,"17":86,"18":120,"19":144,"20":18,"21":52,"22":86,"23":120,"24":144,"25":18,"26":52,"27":86,"28":120,"29":144,"30":18,"31":52}`, + }, { // tests toWord with byte array length > 32 + code: "{step: function() {}, fault: function() {}, result: function() { return toWord('0x1234567890123456789012345678901234567890123456789012345678901234567890'); }}", + want: `{"0":120,"1":144,"2":18,"3":52,"4":86,"5":120,"6":144,"7":18,"8":52,"9":86,"10":120,"11":144,"12":18,"13":52,"14":86,"15":120,"16":144,"17":18,"18":52,"19":86,"20":120,"21":144,"22":18,"23":52,"24":86,"25":120,"26":144,"27":18,"28":52,"29":86,"30":120,"31":144}`, }, { // test feeding a buffer back into go code: "{res: null, step: function(log) { var address = log.contract.getAddress(); this.res = toAddress(address); }, fault: function() {}, result: function() { return this.res }}", want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}`, From 20ad4f500e7fafab93f6d94fa171a5c0309de6ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Thu, 22 May 2025 11:30:20 +0200 Subject: [PATCH 044/365] core/txpool: add explicit max blob count limit (#31837) Fixes #31792. --------- Co-authored-by: lightclient --- core/txpool/blobpool/blobpool.go | 15 +++++-- core/txpool/blobpool/blobpool_test.go | 59 +++++++++++++++++++++++++++ core/txpool/errors.go | 4 ++ core/txpool/validation.go | 10 +++-- 4 files changed, 81 insertions(+), 7 deletions(-) diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index e506da228d..2602d82104 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -62,6 +62,12 @@ const ( // limit can never hurt. txMaxSize = 1024 * 1024 + // maxBlobsPerTx is the maximum number of blobs that a single transaction can + // carry. We choose a smaller limit than the protocol-permitted MaxBlobsPerBlock + // in order to ensure network and txpool stability. + // Note: if you increase this, validation will fail on txMaxSize. + maxBlobsPerTx = 7 + // maxTxsPerAccount is the maximum number of blob transactions admitted from // a single account. The limit is enforced to minimize the DoS potential of // a private tx cancelling publicly propagated blobs. @@ -1095,10 +1101,11 @@ func (p *BlobPool) SetGasTip(tip *big.Int) { // and does not require the pool mutex to be held. func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error { opts := &txpool.ValidationOptions{ - Config: p.chain.Config(), - Accept: 1 << types.BlobTxType, - MaxSize: txMaxSize, - MinTip: p.gasTip.ToBig(), + Config: p.chain.Config(), + Accept: 1 << types.BlobTxType, + MaxSize: txMaxSize, + MinTip: p.gasTip.ToBig(), + MaxBlobCount: maxBlobsPerTx, } return txpool.ValidateTransaction(tx, p.head, p.signer, opts) } diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 0a323179a6..12b64bf674 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -1142,6 +1142,65 @@ func TestChangingSlotterSize(t *testing.T) { } } +// TestBlobCountLimit tests the blobpool enforced limits on the max blob count. +func TestBlobCountLimit(t *testing.T) { + var ( + key1, _ = crypto.GenerateKey() + key2, _ = crypto.GenerateKey() + + addr1 = crypto.PubkeyToAddress(key1.PublicKey) + addr2 = crypto.PubkeyToAddress(key2.PublicKey) + ) + + statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) + statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) + statedb.Commit(0, true, false) + + // Make Prague-enabled custom chain config. + cancunTime := uint64(0) + pragueTime := uint64(0) + config := ¶ms.ChainConfig{ + ChainID: big.NewInt(1), + LondonBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + CancunTime: &cancunTime, + PragueTime: &pragueTime, + BlobScheduleConfig: ¶ms.BlobScheduleConfig{ + Cancun: params.DefaultCancunBlobConfig, + Prague: params.DefaultPragueBlobConfig, + }, + } + chain := &testBlockChain{ + config: config, + basefee: uint256.NewInt(1050), + blobfee: uint256.NewInt(105), + statedb: statedb, + } + pool := New(Config{Datadir: t.TempDir()}, chain, nil) + if err := pool.Init(1, chain.CurrentBlock(), newReserver()); err != nil { + t.Fatalf("failed to create blob pool: %v", err) + } + + // Attempt to add transactions. + var ( + tx1 = makeMultiBlobTx(0, 1, 1000, 100, 7, key1) + tx2 = makeMultiBlobTx(0, 1, 800, 70, 8, key2) + ) + errs := pool.Add([]*types.Transaction{tx1, tx2}, true) + + // Check that first succeeds second fails. + if errs[0] != nil { + t.Fatalf("expected tx with 7 blobs to succeed") + } + if !errors.Is(errs[1], txpool.ErrTxBlobLimitExceeded) { + t.Fatalf("expected tx with 8 blobs to fail, got: %v", errs[1]) + } + + verifyPoolInternals(t, pool) + pool.Close() +} + // Tests that adding transaction will correctly store it in the persistent store // and update all the indices. // diff --git a/core/txpool/errors.go b/core/txpool/errors.go index 968c9d9542..9bc435d67e 100644 --- a/core/txpool/errors.go +++ b/core/txpool/errors.go @@ -58,6 +58,10 @@ var ( // making the transaction invalid, rather a DOS protection. ErrOversizedData = errors.New("oversized data") + // ErrTxBlobLimitExceeded is returned if a transaction would exceed the number + // of blobs allowed by blobpool. + ErrTxBlobLimitExceeded = errors.New("transaction blob limit exceeded") + // ErrAlreadyReserved is returned if the sender address has a pending transaction // in a different subpool. For example, this error is returned in response to any // input transaction of non-blob type when a blob transaction from this sender diff --git a/core/txpool/validation.go b/core/txpool/validation.go index e370f2ce84..720d0d3b72 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -42,9 +42,10 @@ var ( type ValidationOptions struct { Config *params.ChainConfig // Chain configuration to selectively validate based on current fork rules - Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool - MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle - MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool + Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool + MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle + MaxBlobCount int // Maximum number of blobs allowed per transaction + MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool } // ValidationFunction is an method type which the pools use to perform the tx-validations which do not @@ -63,6 +64,9 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types if opts.Accept&(1< opts.MaxBlobCount { + return fmt.Errorf("%w: blob count %v, limit %v", ErrTxBlobLimitExceeded, blobCount, opts.MaxBlobCount) + } // Before performing any expensive validations, sanity check that the tx is // smaller than the maximum limit the pool can meaningfully handle if tx.Size() > opts.MaxSize { From 29a87e442645bc34d08e5c8709c619411c6c3624 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Thu, 22 May 2025 15:49:11 -0600 Subject: [PATCH 045/365] build: Update EEST to v4.5.0 (#31880) We deleted outdated pectra-devnet-6@v1.0.0 release by mistake, so this PR updates the referenced EEST release to the correct latest version. @s1na I removed the TODO comment because I think this solves it, unless it meant something else. --------- Co-authored-by: MariusVanDerWijden --- build/checksums.txt | 6 +++--- build/ci.go | 2 +- tests/block_test.go | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/build/checksums.txt b/build/checksums.txt index c819429969..cf52172c2e 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -1,9 +1,9 @@ # This file contains sha256 checksums of optional build dependencies. -# version:spec-tests pectra-devnet-6@v1.0.0 +# version:spec-tests v4.5.0 # https://github.com/ethereum/execution-spec-tests/releases -# https://github.com/ethereum/execution-spec-tests/releases/download/pectra-devnet-6%40v1.0.0/ -b69211752a3029083c020dc635fe12156ca1a6725a08559da540a0337586a77e fixtures_pectra-devnet-6.tar.gz +# https://github.com/ethereum/execution-spec-tests/releases/download/v4.5.0/ +58afb92a0075a2cb7c4dec1281f7cb88b21b02afbedad096b580f3f8cc14c54c fixtures_develop.tar.gz # version:golang 1.24.3 # https://go.dev/dl/ diff --git a/build/ci.go b/build/ci.go index 88e4e82282..58c769e0d7 100644 --- a/build/ci.go +++ b/build/ci.go @@ -332,7 +332,7 @@ func doTest(cmdline []string) { // downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures. func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string { ext := ".tar.gz" - base := "fixtures_pectra-devnet-6" // TODO(s1na) rename once the version becomes part of the filename + base := "fixtures_develop" archivePath := filepath.Join(cachedir, base+ext) if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil { log.Fatal(err) diff --git a/tests/block_test.go b/tests/block_test.go index f146e4ee6a..91d9f2e653 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -81,6 +81,9 @@ func TestExecutionSpecBlocktests(t *testing.T) { } bt := new(testMatcher) + bt.skipLoad(".*prague/eip7251_consolidations/contract_deployment/system_contract_deployment.json") + bt.skipLoad(".*prague/eip7002_el_triggerable_withdrawals/contract_deployment/system_contract_deployment.json") + bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) { execBlockTest(t, bt, test) }) From 1fd806d3e59b1da29297611e0046df0bc742658d Mon Sep 17 00:00:00 2001 From: Merkel Tranjes <140164174+rnkrtt@users.noreply.github.com> Date: Fri, 23 May 2025 09:21:03 +0200 Subject: [PATCH 046/365] internal/era: update link to documentation (#31879) Updated reference URL in accumulator.go comment to point to the correct location of the historical-hashes-accumulator documentation in the Ethereum portal network specs --- internal/era/accumulator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/era/accumulator.go b/internal/era/accumulator.go index cb383d8e63..83a761f1fd 100644 --- a/internal/era/accumulator.go +++ b/internal/era/accumulator.go @@ -49,7 +49,7 @@ func ComputeAccumulator(hashes []common.Hash, tds []*big.Int) (common.Hash, erro // headerRecord is an individual record for a historical header. // -// See https://github.com/ethereum/portal-network-specs/blob/master/history-network.md#the-header-accumulator +// See https://github.com/ethereum/portal-network-specs/blob/master/history/history-network.md#the-historical-hashes-accumulator // for more information. type headerRecord struct { Hash common.Hash From a53fdf1fe6eac47899738dccba5a652936aebb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Irmak?= Date: Fri, 23 May 2025 12:14:40 +0300 Subject: [PATCH 047/365] crypto: use pure Go signature implementation in tinygo (#31878) tinygo is having problems compiling the C implementation --- crypto/signature_cgo.go | 4 ++-- crypto/signature_nocgo.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/signature_cgo.go b/crypto/signature_cgo.go index 5c7810c14c..18b78f4aac 100644 --- a/crypto/signature_cgo.go +++ b/crypto/signature_cgo.go @@ -14,8 +14,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -//go:build !nacl && !js && !wasip1 && cgo && !gofuzz -// +build !nacl,!js,!wasip1,cgo,!gofuzz +//go:build !nacl && !js && !wasip1 && cgo && !gofuzz && !tinygo +// +build !nacl,!js,!wasip1,cgo,!gofuzz,!tinygo package crypto diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index 2d35b49403..d76127c258 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -14,8 +14,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -//go:build nacl || js || wasip1 || !cgo || gofuzz -// +build nacl js wasip1 !cgo gofuzz +//go:build nacl || js || wasip1 || !cgo || gofuzz || tinygo +// +build nacl js wasip1 !cgo gofuzz tinygo package crypto From f21adaf245e320a809f9bb6ec96c330726c9078f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Irmak?= Date: Fri, 23 May 2025 12:29:01 +0300 Subject: [PATCH 048/365] consensus: remove clique RPC APIs (#31875) --- consensus/beacon/consensus.go | 6 - consensus/clique/api.go | 235 ---------------------------------- consensus/clique/clique.go | 10 -- consensus/consensus.go | 4 - consensus/ethash/ethash.go | 7 - eth/backend.go | 3 - 6 files changed, 265 deletions(-) delete mode 100644 consensus/clique/api.go diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index cc9f44e460..f9a5a3233b 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" ) @@ -445,11 +444,6 @@ func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uin return beaconDifficulty } -// APIs implements consensus.Engine, returning the user facing RPC APIs. -func (beacon *Beacon) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return beacon.ethone.APIs(chain) -} - // Close shutdowns the consensus engine func (beacon *Beacon) Close() error { return beacon.ethone.Close() diff --git a/consensus/clique/api.go b/consensus/clique/api.go deleted file mode 100644 index 374b50692d..0000000000 --- a/consensus/clique/api.go +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2017 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 . - -package clique - -import ( - "encoding/json" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" -) - -// API is a user facing RPC API to allow controlling the signer and voting -// mechanisms of the proof-of-authority scheme. -type API struct { - chain consensus.ChainHeaderReader - clique *Clique -} - -// GetSnapshot retrieves the state snapshot at a given block. -func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { - // Retrieve the requested block number (or current if none requested) - var header *types.Header - if number == nil || *number == rpc.LatestBlockNumber { - header = api.chain.CurrentHeader() - } else { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - // Ensure we have an actually valid block and return its snapshot - if header == nil { - return nil, errUnknownBlock - } - return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) -} - -// GetSnapshotAtHash retrieves the state snapshot at a given block. -func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { - header := api.chain.GetHeaderByHash(hash) - if header == nil { - return nil, errUnknownBlock - } - return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) -} - -// GetSigners retrieves the list of authorized signers at the specified block. -func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) { - // Retrieve the requested block number (or current if none requested) - var header *types.Header - if number == nil || *number == rpc.LatestBlockNumber { - header = api.chain.CurrentHeader() - } else { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - // Ensure we have an actually valid block and return the signers from its snapshot - if header == nil { - return nil, errUnknownBlock - } - snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) - if err != nil { - return nil, err - } - return snap.signers(), nil -} - -// GetSignersAtHash retrieves the list of authorized signers at the specified block. -func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) { - header := api.chain.GetHeaderByHash(hash) - if header == nil { - return nil, errUnknownBlock - } - snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) - if err != nil { - return nil, err - } - return snap.signers(), nil -} - -// Proposals returns the current proposals the node tries to uphold and vote on. -func (api *API) Proposals() map[common.Address]bool { - api.clique.lock.RLock() - defer api.clique.lock.RUnlock() - - proposals := make(map[common.Address]bool) - for address, auth := range api.clique.proposals { - proposals[address] = auth - } - return proposals -} - -// Propose injects a new authorization proposal that the signer will attempt to -// push through. -func (api *API) Propose(address common.Address, auth bool) { - api.clique.lock.Lock() - defer api.clique.lock.Unlock() - - api.clique.proposals[address] = auth -} - -// Discard drops a currently running proposal, stopping the signer from casting -// further votes (either for or against). -func (api *API) Discard(address common.Address) { - api.clique.lock.Lock() - defer api.clique.lock.Unlock() - - delete(api.clique.proposals, address) -} - -type status struct { - InturnPercent float64 `json:"inturnPercent"` - SigningStatus map[common.Address]int `json:"sealerActivity"` - NumBlocks uint64 `json:"numBlocks"` -} - -// Status returns the status of the last N blocks, -// - the number of active signers, -// - the number of signers, -// - the percentage of in-turn blocks -func (api *API) Status() (*status, error) { - var ( - numBlocks = uint64(64) - header = api.chain.CurrentHeader() - diff = uint64(0) - optimals = 0 - ) - snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) - if err != nil { - return nil, err - } - var ( - signers = snap.signers() - end = header.Number.Uint64() - start = end - numBlocks - ) - if numBlocks > end { - start = 1 - numBlocks = end - start - } - signStatus := make(map[common.Address]int) - for _, s := range signers { - signStatus[s] = 0 - } - for n := start; n < end; n++ { - h := api.chain.GetHeaderByNumber(n) - if h == nil { - return nil, fmt.Errorf("missing block %d", n) - } - if h.Difficulty.Cmp(diffInTurn) == 0 { - optimals++ - } - diff += h.Difficulty.Uint64() - sealer, err := api.clique.Author(h) - if err != nil { - return nil, err - } - signStatus[sealer]++ - } - return &status{ - InturnPercent: float64(100*optimals) / float64(numBlocks), - SigningStatus: signStatus, - NumBlocks: numBlocks, - }, nil -} - -type blockNumberOrHashOrRLP struct { - *rpc.BlockNumberOrHash - RLP hexutil.Bytes `json:"rlp,omitempty"` -} - -func (sb *blockNumberOrHashOrRLP) UnmarshalJSON(data []byte) error { - bnOrHash := new(rpc.BlockNumberOrHash) - // Try to unmarshal bNrOrHash - if err := bnOrHash.UnmarshalJSON(data); err == nil { - sb.BlockNumberOrHash = bnOrHash - return nil - } - // Try to unmarshal RLP - var input string - if err := json.Unmarshal(data, &input); err != nil { - return err - } - blob, err := hexutil.Decode(input) - if err != nil { - return err - } - sb.RLP = blob - return nil -} - -// GetSigner returns the signer for a specific clique block. -// Can be called with a block number, a block hash or a rlp encoded blob. -// The RLP encoded blob can either be a block or a header. -func (api *API) GetSigner(rlpOrBlockNr *blockNumberOrHashOrRLP) (common.Address, error) { - if len(rlpOrBlockNr.RLP) == 0 { - blockNrOrHash := rlpOrBlockNr.BlockNumberOrHash - var header *types.Header - if blockNrOrHash == nil { - header = api.chain.CurrentHeader() - } else if hash, ok := blockNrOrHash.Hash(); ok { - header = api.chain.GetHeaderByHash(hash) - } else if number, ok := blockNrOrHash.Number(); ok { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - if header == nil { - return common.Address{}, fmt.Errorf("missing block %v", blockNrOrHash.String()) - } - return api.clique.Author(header) - } - block := new(types.Block) - if err := rlp.DecodeBytes(rlpOrBlockNr.RLP, block); err == nil { - return api.clique.Author(block.Header()) - } - header := new(types.Header) - if err := rlp.DecodeBytes(rlpOrBlockNr.RLP, header); err != nil { - return common.Address{}, err - } - return api.clique.Author(header) -} diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index d31efd7445..b593d2117d 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -41,7 +41,6 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" "golang.org/x/crypto/sha3" ) @@ -641,15 +640,6 @@ func (c *Clique) Close() error { return nil } -// APIs implements consensus.Engine, returning the user facing RPC API to allow -// controlling the signer voting. -func (c *Clique) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return []rpc.API{{ - Namespace: "clique", - Service: &API{chain: chain, clique: c}, - }} -} - // SealHash returns the hash of a block prior to it being sealed. func SealHash(header *types.Header) (hash common.Hash) { hasher := sha3.NewLegacyKeccak256() diff --git a/consensus/consensus.go b/consensus/consensus.go index c59b9a4744..a68351f7ff 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" ) // ChainHeaderReader defines a small collection of methods needed to access the local @@ -109,9 +108,6 @@ type Engine interface { // that a new block should have. CalcDifficulty(chain ChainHeaderReader, time uint64, parent *types.Header) *big.Int - // APIs returns the RPC APIs this consensus engine provides. - APIs(chain ChainHeaderReader) []rpc.API - // Close terminates any background threads maintained by the consensus engine. Close() error } diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go index f37ec26056..f624f73875 100644 --- a/consensus/ethash/ethash.go +++ b/consensus/ethash/ethash.go @@ -22,7 +22,6 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rpc" ) // Ethash is a consensus engine based on proof-of-work implementing the ethash @@ -71,12 +70,6 @@ func (ethash *Ethash) Close() error { return nil } -// APIs implements consensus.Engine, returning no APIs as ethash is an empty -// shell in the post-merge world. -func (ethash *Ethash) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return []rpc.API{} -} - // Seal generates a new sealing request for the given input block and pushes // the result into the given channel. For the ethash engine, this method will // just panic as sealing is not supported anymore. diff --git a/eth/backend.go b/eth/backend.go index 6d1b6bae99..15243ad5c9 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -337,9 +337,6 @@ func makeExtraData(extra []byte) []byte { func (s *Ethereum) APIs() []rpc.API { apis := ethapi.GetAPIs(s.APIBackend) - // Append any APIs exposed explicitly by the consensus engine - apis = append(apis, s.engine.APIs(s.BlockChain())...) - // Append all the local APIs and return return append(apis, []rpc.API{ { From 94481d13513f94ef4a76ef847e7c3d436fde2546 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 23 May 2025 12:33:43 +0200 Subject: [PATCH 049/365] .gitea: add initial workflow file (#31885) --- .gitea/workflows/release.yml | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .gitea/workflows/release.yml diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000000..fa7b7f25ab --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,38 @@ +name: Release Builds + +on: + push: + branches: [ master ] + +jobs: + docker: + name: Docker Image + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.0 + cache: false + + - name: Run docker build + run: | + go run build/ci.go docker -platform linux/amd64,linux/arm64 + + linux: + name: Docker Image + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.0 + cache: false + + - name: Run build + run: | + go run build/ci.go install From 8f598e85ade64653b6490b8ca742a51274ec328a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 23 May 2025 12:44:30 +0200 Subject: [PATCH 050/365] .gitea: update release build actions (#31886) Trying to make the docker build work. --- .gitea/workflows/release.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index fa7b7f25ab..4a169127ea 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -11,18 +11,24 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.23.0 + go-version: 1.24 cache: false - name: Run docker build run: | - go run build/ci.go docker -platform linux/amd64,linux/arm64 + go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 linux: - name: Docker Image + name: Linux Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -30,7 +36,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.23.0 + go-version: 1.24 cache: false - name: Run build From 8781e93013d286538a8848b695f2b1e102f4af6a Mon Sep 17 00:00:00 2001 From: buddho Date: Fri, 23 May 2025 19:10:10 +0800 Subject: [PATCH 051/365] core/state: fix copy of storageChange (#31874) Missing field origvalue when copying storageChange. --- core/state/journal.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/state/journal.go b/core/state/journal.go index 13332dbd79..f3f976f24f 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -408,6 +408,7 @@ func (ch storageChange) copy() journalEntry { account: ch.account, key: ch.key, prevvalue: ch.prevvalue, + origvalue: ch.origvalue, } } From b97198379b824d8e331d9e024afead4fe03cc50a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 23 May 2025 16:21:08 +0200 Subject: [PATCH 052/365] .gitea: add cron build script (#31890) Also swaps the push build scripts and adds environment output. --- .gitea/workflows/release-cron.yml | 42 +++++++++++++++++++++++++++++++ .gitea/workflows/release.yml | 34 ++++++++++++++----------- 2 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 .gitea/workflows/release-cron.yml diff --git a/.gitea/workflows/release-cron.yml b/.gitea/workflows/release-cron.yml new file mode 100644 index 0000000000..3a03d0ef14 --- /dev/null +++ b/.gitea/workflows/release-cron.yml @@ -0,0 +1,42 @@ +name: Release Builds (cron) + +on: + schedule: + cron: '0 0 * * *' + +jobs: + azure-cleanup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.24 + cache: false + + - name: Run cleanup script + run: | + go run build/ci.go purge -store gethstore/builds -days 14 + + ppa: + name: PPA Upload (master) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.24 + cache: false + + - name: Install deb toolchain + run: | + apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot + + - name: Run ci.go + run: | + 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 " diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 4a169127ea..a91bebda7f 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -1,44 +1,48 @@ -name: Release Builds +name: Release Builds (push) on: push: branches: [ master ] jobs: - docker: - name: Docker Image + linux: + name: Linux Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Set up Go uses: actions/setup-go@v5 with: go-version: 1.24 cache: false - - name: Run docker build + - name: display environment run: | - go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 + env - linux: - name: Linux Build + - name: Run build + run: | + go run build/ci.go install + + docker: + name: Docker Image runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Set up Go uses: actions/setup-go@v5 with: go-version: 1.24 cache: false - - name: Run build + - name: Run docker build run: | - go run build/ci.go install + go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 From f14813fea99f69d5ff11a6e0c96aebd44a2fc288 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 23 May 2025 17:48:15 +0200 Subject: [PATCH 053/365] internal/build: add support for Github Actions CI environment (#31891) This adds support for the Github actions environment in the build tool. Information from environment variables, like the build number and branch/tag name, is used to make decisions about uploads and package filenames. --- internal/build/env.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/internal/build/env.go b/internal/build/env.go index 35b2cd6ae7..23501d0ece 100644 --- a/internal/build/env.go +++ b/internal/build/env.go @@ -92,6 +92,33 @@ func Env() Environment { IsPullRequest: os.Getenv("APPVEYOR_PULL_REQUEST_NUMBER") != "", IsCronJob: os.Getenv("APPVEYOR_SCHEDULED_BUILD") == "True", } + case os.Getenv("CI") == "true" && os.Getenv("GITHUB_ACTIONS") == "true": + commit := os.Getenv("GITHUB_SHA") + reftype := os.Getenv("GITHUB_REF_TYPE") + isPR := os.Getenv("GITHUB_HEAD_REF") != "" + tag := "" + branch := "" + switch { + case isPR: + branch = os.Getenv("GITHUB_BASE_REF") + case reftype == "branch": + branch = os.Getenv("GITHUB_REF_NAME") + case reftype == "tag": + tag = os.Getenv("GITHUB_REF_NAME") + } + return Environment{ + CI: true, + Name: "github-actions", + Repo: os.Getenv("GITHUB_REPOSITORY"), + Commit: commit, + Date: getDate(commit), + Branch: branch, + Tag: tag, + IsPullRequest: isPR, + Buildnum: os.Getenv("GITHUB_RUN_ID"), + IsCronJob: os.Getenv("GITHUB_EVENT_NAME") == "schedule", + } + default: return LocalEnv() } From 9fd3f8a0dd0a82514bf0ab5ed65dbdcf48c5e155 Mon Sep 17 00:00:00 2001 From: Marcel <153717436+MonkeyMarcel@users.noreply.github.com> Date: Fri, 23 May 2025 23:50:25 +0800 Subject: [PATCH 054/365] core: remove unused queued import status (#31870) --- core/blockchain_insert.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index 695aa6679b..d7c2696f08 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -27,10 +27,10 @@ import ( // insertStats tracks and reports on block insertion. type insertStats struct { - queued, processed, ignored int - usedGas uint64 - lastIndex int - startTime mclock.AbsTime + processed, ignored int + usedGas uint64 + lastIndex int + startTime mclock.AbsTime } // statsReportLimit is the time limit during import and export after which we @@ -78,9 +78,6 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn } context = append(context, []interface{}{"triedirty", triebufNodes}...) - if st.queued > 0 { - context = append(context, []interface{}{"queued", st.queued}...) - } if st.ignored > 0 { context = append(context, []interface{}{"ignored", st.ignored}...) } From 3f7b8bc976fe5e9b810b91da359b3e0cb7d010c8 Mon Sep 17 00:00:00 2001 From: Sina M <1591639+s1na@users.noreply.github.com> Date: Mon, 26 May 2025 10:45:41 +0200 Subject: [PATCH 055/365] core/vm: fix bls benchmark (#31896) Fixes #31893 --- core/vm/contracts_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index b627f2ada5..537d787757 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -370,7 +370,7 @@ func BenchmarkPrecompiledBLS12381G1MultiExpWorstCase(b *testing.B) { Name: "WorstCaseG1", NoBenchmark: false, } - benchmarkPrecompiled("f0c", testcase, b) + benchmarkPrecompiled("f0b", testcase, b) } // BenchmarkPrecompiledBLS12381G2MultiExpWorstCase benchmarks the worst case we could find that still fits a gaslimit of 10MGas. @@ -391,5 +391,5 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) { Name: "WorstCaseG2", NoBenchmark: false, } - benchmarkPrecompiled("f0f", testcase, b) + benchmarkPrecompiled("f0d", testcase, b) } From 8b9f2d4e36dfcdb2af94dc0d3b63f30c8ad159a9 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Wed, 28 May 2025 19:31:42 +0800 Subject: [PATCH 056/365] triedb/pathdb: introduce lookup structure to optimize state access (#30971) This pull request introduces a mechanism to improve state lookup efficiency in pathdb by maintaining a lookup structure that eliminates unnecessary iteration over diff layers. The core idea is to track a mutation history for each dirty state entry residing in the diff layers. This history records the state roots of all layers in which the entry was modified, sorted from oldest to newest. During state lookup, this mutation history is queried to find the most recent layer whose state root either matches the target root or is a descendant of it. This allows us to quickly identify the layer containing the relevant data, avoiding the need to iterate through all diff layers from top to bottom. Besides, the overhead for state lookup is constant, no matter how many diff layers are retained in the pathdb, which unlocks the potential to hold more diff layers. Of course, maintaining this lookup structure introduces some overhead. For each state transition, we need to: (a) update the mutation records for the modified state entries, and (b) remove stale mutation records associated with outdated layers. On our benchmark machine, it will introduce around 1ms overhead which is acceptable. --- triedb/pathdb/database.go | 4 +- triedb/pathdb/difflayer.go | 4 +- triedb/pathdb/disklayer.go | 9 - triedb/pathdb/layertree.go | 193 +++++-- triedb/pathdb/layertree_test.go | 885 ++++++++++++++++++++++++++++++++ triedb/pathdb/lookup.go | 278 ++++++++++ triedb/pathdb/metrics.go | 3 + triedb/pathdb/reader.go | 56 +- 8 files changed, 1382 insertions(+), 50 deletions(-) create mode 100644 triedb/pathdb/layertree_test.go create mode 100644 triedb/pathdb/lookup.go diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index c206460315..3174a7c964 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -487,7 +487,7 @@ func (db *Database) Enable(root common.Hash) error { // Re-construct a new disk layer backed by persistent state // and schedule the state snapshot generation if it's permitted. - db.tree.reset(generateSnapshot(db, root, db.isVerkle || db.config.SnapshotNoBuild)) + db.tree.init(generateSnapshot(db, root, db.isVerkle || db.config.SnapshotNoBuild)) log.Info("Rebuilt trie database", "root", root) return nil } @@ -529,7 +529,7 @@ func (db *Database) Recover(root common.Hash) error { // reset layer with newly created disk layer. It must be // done after each revert operation, otherwise the new // disk layer won't be accessible from outside. - db.tree.reset(dl) + db.tree.init(dl) } rawdb.DeleteTrieJournal(db.diskdb) diff --git a/triedb/pathdb/difflayer.go b/triedb/pathdb/difflayer.go index 2e1d83c74a..ac05b4a0fb 100644 --- a/triedb/pathdb/difflayer.go +++ b/triedb/pathdb/difflayer.go @@ -156,7 +156,7 @@ func (dl *diffLayer) update(root common.Hash, id uint64, block uint64, nodes *no } // persist flushes the diff layer and all its parent layers to disk layer. -func (dl *diffLayer) persist(force bool) (layer, error) { +func (dl *diffLayer) persist(force bool) (*diskLayer, error) { if parent, ok := dl.parentLayer().(*diffLayer); ok { // Hold the lock to prevent any read operation until the new // parent is linked correctly. @@ -183,7 +183,7 @@ func (dl *diffLayer) size() uint64 { // diffToDisk merges a bottom-most diff into the persistent disk layer underneath // it. The method will panic if called onto a non-bottom-most diff layer. -func diffToDisk(layer *diffLayer, force bool) (layer, error) { +func diffToDisk(layer *diffLayer, force bool) (*diskLayer, error) { disk, ok := layer.parentLayer().(*diskLayer) if !ok { panic(fmt.Sprintf("unknown layer type: %T", layer.parentLayer())) diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index bee4cd1e8a..1c9efb024b 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -94,15 +94,6 @@ func (dl *diskLayer) setGenerator(generator *generator) { dl.generator = generator } -// isStale return whether this layer has become stale (was flattened across) or if -// it's still live. -func (dl *diskLayer) isStale() bool { - dl.lock.RLock() - defer dl.lock.RUnlock() - - return dl.stale -} - // markStale sets the stale flag as true. func (dl *diskLayer) markStale() { dl.lock.Lock() diff --git a/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go index 85a5e470e7..b2f3f7f37d 100644 --- a/triedb/pathdb/layertree.go +++ b/triedb/pathdb/layertree.go @@ -31,29 +31,50 @@ import ( // thread-safe to use. However, callers need to ensure the thread-safety // of the referenced layer by themselves. type layerTree struct { - lock sync.RWMutex + base *diskLayer layers map[common.Hash]layer + + // descendants is a two-dimensional map where the keys represent + // an ancestor state root, and the values are the state roots of + // all its descendants. + // + // For example: r -> [c1, c2, ..., cn], where c1 through cn are + // the descendants of state r. + // + // This map includes all the existing diff layers and the disk layer. + descendants map[common.Hash]map[common.Hash]struct{} + lookup *lookup + lock sync.RWMutex } // newLayerTree constructs the layerTree with the given head layer. func newLayerTree(head layer) *layerTree { tree := new(layerTree) - tree.reset(head) + tree.init(head) return tree } -// reset initializes the layerTree by the given head layer. -// All the ancestors will be iterated out and linked in the tree. -func (tree *layerTree) reset(head layer) { +// init initializes the layerTree by the given head layer. +func (tree *layerTree) init(head layer) { tree.lock.Lock() defer tree.lock.Unlock() - var layers = make(map[common.Hash]layer) - for head != nil { - layers[head.rootHash()] = head - head = head.parentLayer() + current := head + tree.layers = make(map[common.Hash]layer) + tree.descendants = make(map[common.Hash]map[common.Hash]struct{}) + + for { + tree.layers[current.rootHash()] = current + tree.fillAncestors(current) + + parent := current.parentLayer() + if parent == nil { + break + } + current = parent } - tree.layers = layers + tree.base = current.(*diskLayer) // panic if it's not a disk layer + tree.lookup = newLookup(head, tree.isDescendant) } // get retrieves a layer belonging to the given state root. @@ -64,6 +85,43 @@ func (tree *layerTree) get(root common.Hash) layer { return tree.layers[root] } +// isDescendant returns whether the specified layer with given root is a +// descendant of a specific ancestor. +// +// This function assumes the read lock has been held. +func (tree *layerTree) isDescendant(root common.Hash, ancestor common.Hash) bool { + subset := tree.descendants[ancestor] + if subset == nil { + return false + } + _, ok := subset[root] + return ok +} + +// fillAncestors identifies the ancestors of the given layer and populates the +// descendants set. The ancestors include the diff layers below the supplied +// layer and also the disk layer. +// +// This function assumes the write lock has been held. +func (tree *layerTree) fillAncestors(layer layer) { + hash := layer.rootHash() + for { + parent := layer.parentLayer() + if parent == nil { + break + } + layer = parent + + phash := parent.rootHash() + subset := tree.descendants[phash] + if subset == nil { + subset = make(map[common.Hash]struct{}) + tree.descendants[phash] = subset + } + subset[hash] = struct{}{} + } +} + // forEach iterates the stored layers inside and applies the // given callback on them. func (tree *layerTree) forEach(onLayer func(layer)) { @@ -101,8 +159,16 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6 l := parent.update(root, parent.stateID()+1, block, newNodeSet(nodes.Flatten()), states) tree.lock.Lock() + defer tree.lock.Unlock() + + // Link the given layer into the layer set tree.layers[l.rootHash()] = l - tree.lock.Unlock() + + // Link the given layer into its ancestors (up to the current disk layer) + tree.fillAncestors(l) + + // Link the given layer into the state mutation history + tree.lookup.addLayer(l) return nil } @@ -127,8 +193,16 @@ func (tree *layerTree) cap(root common.Hash, layers int) error { if err != nil { return err } - // Replace the entire layer tree with the flat base - tree.layers = map[common.Hash]layer{base.rootHash(): base} + tree.base = base + + // Reset the layer tree with the single new disk layer + tree.layers = map[common.Hash]layer{ + base.rootHash(): base, + } + // Resets the descendants map, since there's only a single disk layer + // with no descendants. + tree.descendants = make(map[common.Hash]map[common.Hash]struct{}) + tree.lookup = newLookup(base, tree.isDescendant) return nil } // Dive until we run out of layers or reach the persistent database @@ -143,6 +217,11 @@ func (tree *layerTree) cap(root common.Hash, layers int) error { } // We're out of layers, flatten anything below, stopping if it's the disk or if // the memory limit is not yet exceeded. + var ( + err error + replaced layer + newBase *diskLayer + ) switch parent := diff.parentLayer().(type) { case *diskLayer: return nil @@ -152,14 +231,33 @@ func (tree *layerTree) cap(root common.Hash, layers int) error { // parent is linked correctly. diff.lock.Lock() - base, err := parent.persist(false) + // Hold the reference of the original layer being replaced + replaced = parent + + // Replace the original parent layer with new disk layer. The procedure + // can be illustrated as below: + // + // Before change: + // Chain: + // C1->C2->C3->C4 (HEAD) + // ->C2'->C3'->C4' + // + // After change: + // Chain: + // (a) C3->C4 (HEAD) + // (b) C1->C2 + // ->C2'->C3'->C4' + // The original C3 is replaced by the new base (with root C3) + // Dangling layers in (b) will be removed later + newBase, err = parent.persist(false) if err != nil { diff.lock.Unlock() return err } - tree.layers[base.rootHash()] = base - diff.parent = base + tree.layers[newBase.rootHash()] = newBase + // Link the new parent and release the lock + diff.parent = newBase diff.lock.Unlock() default: @@ -173,19 +271,28 @@ func (tree *layerTree) cap(root common.Hash, layers int) error { children[parent] = append(children[parent], root) } } + clearDiff := func(layer layer) { + diff, ok := layer.(*diffLayer) + if !ok { + return + } + tree.lookup.removeLayer(diff) + } var remove func(root common.Hash) remove = func(root common.Hash) { + clearDiff(tree.layers[root]) + + // Unlink the layer from the layer tree and cascade to its children + delete(tree.descendants, root) delete(tree.layers, root) for _, child := range children[root] { remove(child) } delete(children, root) } - for root, layer := range tree.layers { - if dl, ok := layer.(*diskLayer); ok && dl.isStale() { - remove(root) - } - } + remove(tree.base.rootHash()) // remove the old/stale disk layer + clearDiff(replaced) // remove the lookup data of the stale parent being replaced + tree.base = newBase // update the base layer with newly constructed one return nil } @@ -194,17 +301,41 @@ func (tree *layerTree) bottom() *diskLayer { tree.lock.RLock() defer tree.lock.RUnlock() - if len(tree.layers) == 0 { - return nil // Shouldn't happen, empty tree + return tree.base +} + +// lookupAccount returns the layer that is guaranteed to contain the account data +// corresponding to the specified state root being queried. +func (tree *layerTree) lookupAccount(accountHash common.Hash, state common.Hash) (layer, error) { + // Hold the read lock to prevent the unexpected layer changes + tree.lock.RLock() + defer tree.lock.RUnlock() + + tip := tree.lookup.accountTip(accountHash, state, tree.base.root) + if tip == (common.Hash{}) { + return nil, fmt.Errorf("[%#x] %w", state, errSnapshotStale) } - // pick a random one as the entry point - var current layer - for _, layer := range tree.layers { - current = layer - break + l := tree.layers[tip] + if l == nil { + return nil, fmt.Errorf("triedb layer [%#x] missing", tip) } - for current.parentLayer() != nil { - current = current.parentLayer() + return l, nil +} + +// lookupStorage returns the layer that is guaranteed to contain the storage slot +// data corresponding to the specified state root being queried. +func (tree *layerTree) lookupStorage(accountHash common.Hash, slotHash common.Hash, state common.Hash) (layer, error) { + // Hold the read lock to prevent the unexpected layer changes + tree.lock.RLock() + defer tree.lock.RUnlock() + + tip := tree.lookup.storageTip(accountHash, slotHash, state, tree.base.root) + if tip == (common.Hash{}) { + return nil, fmt.Errorf("[%#x] %w", state, errSnapshotStale) + } + l := tree.layers[tip] + if l == nil { + return nil, fmt.Errorf("triedb layer [%#x] missing", tip) } - return current.(*diskLayer) + return l, nil } diff --git a/triedb/pathdb/layertree_test.go b/triedb/pathdb/layertree_test.go new file mode 100644 index 0000000000..a72ff5899e --- /dev/null +++ b/triedb/pathdb/layertree_test.go @@ -0,0 +1,885 @@ +// Copyright 2024 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 + +package pathdb + +import ( + "errors" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/trie/trienode" +) + +func newTestLayerTree() *layerTree { + db := New(rawdb.NewMemoryDatabase(), nil, false) + l := newDiskLayer(common.Hash{0x1}, 0, db, nil, nil, newBuffer(0, nil, nil, 0)) + t := newLayerTree(l) + return t +} + +func TestLayerCap(t *testing.T) { + var cases = []struct { + init func() *layerTree + head common.Hash + layers int + base common.Hash + snapshot map[common.Hash]struct{} + }{ + { + // Chain: + // C1->C2->C3->C4 (HEAD) + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + // Chain: + // C2->C3->C4 (HEAD) + head: common.Hash{0x4}, + layers: 2, + base: common.Hash{0x2}, + snapshot: map[common.Hash]struct{}{ + common.Hash{0x2}: {}, + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + // Chain: + // C3->C4 (HEAD) + head: common.Hash{0x4}, + layers: 1, + base: common.Hash{0x3}, + snapshot: map[common.Hash]struct{}{ + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + // Chain: + // C4 (HEAD) + head: common.Hash{0x4}, + layers: 0, + base: common.Hash{0x4}, + snapshot: map[common.Hash]struct{}{ + common.Hash{0x4}: {}, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + // ->C2'->C3'->C4' + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + // Chain: + // C2->C3->C4 (HEAD) + head: common.Hash{0x4a}, + layers: 2, + base: common.Hash{0x2a}, + snapshot: map[common.Hash]struct{}{ + common.Hash{0x4a}: {}, + common.Hash{0x3a}: {}, + common.Hash{0x2a}: {}, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + // ->C2'->C3'->C4' + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + // Chain: + // C3->C4 (HEAD) + head: common.Hash{0x4a}, + layers: 1, + base: common.Hash{0x3a}, + snapshot: map[common.Hash]struct{}{ + common.Hash{0x4a}: {}, + common.Hash{0x3a}: {}, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + // ->C3'->C4' + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3a}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3b}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + // Chain: + // C2->C3->C4 (HEAD) + // ->C3'->C4' + head: common.Hash{0x4a}, + layers: 2, + base: common.Hash{0x2}, + snapshot: map[common.Hash]struct{}{ + common.Hash{0x4a}: {}, + common.Hash{0x3a}: {}, + common.Hash{0x4b}: {}, + common.Hash{0x3b}: {}, + common.Hash{0x2}: {}, + }, + }, + } + for _, c := range cases { + tr := c.init() + if err := tr.cap(c.head, c.layers); err != nil { + t.Fatalf("Failed to cap the layer tree %v", err) + } + if tr.bottom().root != c.base { + t.Fatalf("Unexpected bottom layer tree root, want %v, got %v", c.base, tr.bottom().root) + } + if len(c.snapshot) != len(tr.layers) { + t.Fatalf("Unexpected layer tree size, want %v, got %v", len(c.snapshot), len(tr.layers)) + } + for h := range tr.layers { + if _, ok := c.snapshot[h]; !ok { + t.Fatalf("Unexpected layer %v", h) + } + } + } +} + +func TestBaseLayer(t *testing.T) { + tr := newTestLayerTree() + + var cases = []struct { + op func() + base common.Hash + }{ + // Chain: + // C1 (HEAD) + { + func() {}, + common.Hash{0x1}, + }, + // Chain: + // C1->C2->C3 (HEAD) + { + func() { + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + }, + common.Hash{0x1}, + }, + // Chain: + // C3 (HEAD) + { + func() { + tr.cap(common.Hash{0x3}, 0) + }, + common.Hash{0x3}, + }, + // Chain: + // C4->C5->C6 (HEAD) + { + func() { + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x5}, common.Hash{0x4}, 4, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x6}, common.Hash{0x5}, 5, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.cap(common.Hash{0x6}, 2) + }, + common.Hash{0x4}, + }, + } + for _, c := range cases { + c.op() + if tr.base.rootHash() != c.base { + t.Fatalf("Unexpected base root, want %v, got: %v", c.base, tr.base.rootHash()) + } + } +} + +func TestDescendant(t *testing.T) { + var cases = []struct { + init func() *layerTree + snapshotA map[common.Hash]map[common.Hash]struct{} + op func(tr *layerTree) + snapshotB map[common.Hash]map[common.Hash]struct{} + }{ + { + // Chain: + // C1->C2 (HEAD) + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + snapshotA: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2}: {}, + }, + }, + // Chain: + // C1->C2->C3 (HEAD) + op: func(tr *layerTree) { + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + }, + snapshotB: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2}: {}, + common.Hash{0x3}: {}, + }, + common.Hash{0x2}: { + common.Hash{0x3}: {}, + }, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + snapshotA: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2}: {}, + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + common.Hash{0x2}: { + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + common.Hash{0x3}: { + common.Hash{0x4}: {}, + }, + }, + // Chain: + // C2->C3->C4 (HEAD) + op: func(tr *layerTree) { + tr.cap(common.Hash{0x4}, 2) + }, + snapshotB: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x2}: { + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + common.Hash{0x3}: { + common.Hash{0x4}: {}, + }, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + snapshotA: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2}: {}, + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + common.Hash{0x2}: { + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + common.Hash{0x3}: { + common.Hash{0x4}: {}, + }, + }, + // Chain: + // C3->C4 (HEAD) + op: func(tr *layerTree) { + tr.cap(common.Hash{0x4}, 1) + }, + snapshotB: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x3}: { + common.Hash{0x4}: {}, + }, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + snapshotA: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2}: {}, + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + common.Hash{0x2}: { + common.Hash{0x3}: {}, + common.Hash{0x4}: {}, + }, + common.Hash{0x3}: { + common.Hash{0x4}: {}, + }, + }, + // Chain: + // C4 (HEAD) + op: func(tr *layerTree) { + tr.cap(common.Hash{0x4}, 0) + }, + snapshotB: map[common.Hash]map[common.Hash]struct{}{}, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + // ->C2'->C3'->C4' + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + snapshotA: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2a}: {}, + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + common.Hash{0x2b}: {}, + common.Hash{0x3b}: {}, + common.Hash{0x4b}: {}, + }, + common.Hash{0x2a}: { + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + }, + common.Hash{0x3a}: { + common.Hash{0x4a}: {}, + }, + common.Hash{0x2b}: { + common.Hash{0x3b}: {}, + common.Hash{0x4b}: {}, + }, + common.Hash{0x3b}: { + common.Hash{0x4b}: {}, + }, + }, + // Chain: + // C2->C3->C4 (HEAD) + op: func(tr *layerTree) { + tr.cap(common.Hash{0x4a}, 2) + }, + snapshotB: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x2a}: { + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + }, + common.Hash{0x3a}: { + common.Hash{0x4a}: {}, + }, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + // ->C2'->C3'->C4' + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + snapshotA: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2a}: {}, + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + common.Hash{0x2b}: {}, + common.Hash{0x3b}: {}, + common.Hash{0x4b}: {}, + }, + common.Hash{0x2a}: { + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + }, + common.Hash{0x3a}: { + common.Hash{0x4a}: {}, + }, + common.Hash{0x2b}: { + common.Hash{0x3b}: {}, + common.Hash{0x4b}: {}, + }, + common.Hash{0x3b}: { + common.Hash{0x4b}: {}, + }, + }, + // Chain: + // C3->C4 (HEAD) + op: func(tr *layerTree) { + tr.cap(common.Hash{0x4a}, 1) + }, + snapshotB: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x3a}: { + common.Hash{0x4a}: {}, + }, + }, + }, + { + // Chain: + // C1->C2->C3->C4 (HEAD) + // ->C3'->C4' + init: func() *layerTree { + tr := newTestLayerTree() + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3a}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x3b}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false)) + return tr + }, + snapshotA: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x1}: { + common.Hash{0x2}: {}, + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + common.Hash{0x3b}: {}, + common.Hash{0x4b}: {}, + }, + common.Hash{0x2}: { + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + common.Hash{0x3b}: {}, + common.Hash{0x4b}: {}, + }, + common.Hash{0x3a}: { + common.Hash{0x4a}: {}, + }, + common.Hash{0x3b}: { + common.Hash{0x4b}: {}, + }, + }, + // Chain: + // C2->C3->C4 (HEAD) + // ->C3'->C4' + op: func(tr *layerTree) { + tr.cap(common.Hash{0x4a}, 2) + }, + snapshotB: map[common.Hash]map[common.Hash]struct{}{ + common.Hash{0x2}: { + common.Hash{0x3a}: {}, + common.Hash{0x4a}: {}, + common.Hash{0x3b}: {}, + common.Hash{0x4b}: {}, + }, + common.Hash{0x3a}: { + common.Hash{0x4a}: {}, + }, + common.Hash{0x3b}: { + common.Hash{0x4b}: {}, + }, + }, + }, + } + check := func(setA, setB map[common.Hash]map[common.Hash]struct{}) bool { + if len(setA) != len(setB) { + return false + } + for h, subA := range setA { + subB, ok := setB[h] + if !ok { + return false + } + if len(subA) != len(subB) { + return false + } + for hh := range subA { + if _, ok := subB[hh]; !ok { + return false + } + } + } + return true + } + for _, c := range cases { + tr := c.init() + if !check(c.snapshotA, tr.descendants) { + t.Fatalf("Unexpected descendants") + } + c.op(tr) + if !check(c.snapshotB, tr.descendants) { + t.Fatalf("Unexpected descendants") + } + } +} + +func TestAccountLookup(t *testing.T) { + // Chain: + // C1->C2->C3->C4 (HEAD) + tr := newTestLayerTree() // base = 0x1 + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), + NewStateSetWithOrigin(randomAccountSet("0xa"), nil, nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), + NewStateSetWithOrigin(randomAccountSet("0xb"), nil, nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), + NewStateSetWithOrigin(randomAccountSet("0xa", "0xc"), nil, nil, nil, false)) + + var cases = []struct { + account common.Hash + state common.Hash + expect common.Hash + }{ + { + // unknown account + common.HexToHash("0xd"), common.Hash{0x4}, common.Hash{0x1}, + }, + /* + lookup account from the top + */ + { + common.HexToHash("0xa"), common.Hash{0x4}, common.Hash{0x4}, + }, + { + common.HexToHash("0xb"), common.Hash{0x4}, common.Hash{0x3}, + }, + { + common.HexToHash("0xc"), common.Hash{0x4}, common.Hash{0x4}, + }, + /* + lookup account from the middle + */ + { + common.HexToHash("0xa"), common.Hash{0x3}, common.Hash{0x2}, + }, + { + common.HexToHash("0xb"), common.Hash{0x3}, common.Hash{0x3}, + }, + { + common.HexToHash("0xc"), common.Hash{0x3}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0xa"), common.Hash{0x2}, common.Hash{0x2}, + }, + { + common.HexToHash("0xb"), common.Hash{0x2}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0xc"), common.Hash{0x2}, common.Hash{0x1}, // not found + }, + /* + lookup account from the bottom + */ + { + common.HexToHash("0xa"), common.Hash{0x1}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0xb"), common.Hash{0x1}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0xc"), common.Hash{0x1}, common.Hash{0x1}, // not found + }, + } + for i, c := range cases { + l, err := tr.lookupAccount(c.account, c.state) + if err != nil { + t.Fatalf("%d: %v", i, err) + } + if l.rootHash() != c.expect { + t.Errorf("Unexpected tiphash, %d, want: %x, got: %x", i, c.expect, l.rootHash()) + } + } + + // Chain: + // C3->C4 (HEAD) + tr.cap(common.Hash{0x4}, 1) + + cases2 := []struct { + account common.Hash + state common.Hash + expect common.Hash + expectErr error + }{ + { + // unknown account + common.HexToHash("0xd"), common.Hash{0x4}, common.Hash{0x3}, nil, + }, + /* + lookup account from the top + */ + { + common.HexToHash("0xa"), common.Hash{0x4}, common.Hash{0x4}, nil, + }, + { + common.HexToHash("0xb"), common.Hash{0x4}, common.Hash{0x3}, nil, + }, + { + common.HexToHash("0xc"), common.Hash{0x4}, common.Hash{0x4}, nil, + }, + /* + lookup account from the bottom + */ + { + common.HexToHash("0xa"), common.Hash{0x3}, common.Hash{0x3}, nil, + }, + { + common.HexToHash("0xb"), common.Hash{0x3}, common.Hash{0x3}, nil, + }, + { + common.HexToHash("0xc"), common.Hash{0x3}, common.Hash{0x3}, nil, // not found + }, + /* + stale states + */ + { + common.HexToHash("0xa"), common.Hash{0x2}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0xb"), common.Hash{0x2}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0xc"), common.Hash{0x2}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0xa"), common.Hash{0x1}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0xb"), common.Hash{0x1}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0xc"), common.Hash{0x1}, common.Hash{}, errSnapshotStale, + }, + } + for i, c := range cases2 { + l, err := tr.lookupAccount(c.account, c.state) + if c.expectErr != nil { + if !errors.Is(err, c.expectErr) { + t.Fatalf("%d: unexpected error, want %v, got %v", i, c.expectErr, err) + } + } + if c.expectErr == nil { + if err != nil { + t.Fatalf("%d: %v", i, err) + } + if l.rootHash() != c.expect { + t.Errorf("Unexpected tiphash, %d, want: %x, got: %x", i, c.expect, l.rootHash()) + } + } + } +} + +func TestStorageLookup(t *testing.T) { + // Chain: + // C1->C2->C3->C4 (HEAD) + tr := newTestLayerTree() // base = 0x1 + tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), + NewStateSetWithOrigin(randomAccountSet("0xa"), randomStorageSet([]string{"0xa"}, [][]string{{"0x1"}}, nil), nil, nil, false)) + tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), + NewStateSetWithOrigin(randomAccountSet("0xa"), randomStorageSet([]string{"0xa"}, [][]string{{"0x2"}}, nil), nil, nil, false)) + tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), + NewStateSetWithOrigin(randomAccountSet("0xa"), randomStorageSet([]string{"0xa"}, [][]string{{"0x1", "0x3"}}, nil), nil, nil, false)) + + var cases = []struct { + storage common.Hash + state common.Hash + expect common.Hash + }{ + { + // unknown storage slot + common.HexToHash("0x4"), common.Hash{0x4}, common.Hash{0x1}, + }, + /* + lookup storage slot from the top + */ + { + common.HexToHash("0x1"), common.Hash{0x4}, common.Hash{0x4}, + }, + { + common.HexToHash("0x2"), common.Hash{0x4}, common.Hash{0x3}, + }, + { + common.HexToHash("0x3"), common.Hash{0x4}, common.Hash{0x4}, + }, + /* + lookup storage slot from the middle + */ + { + common.HexToHash("0x1"), common.Hash{0x3}, common.Hash{0x2}, + }, + { + common.HexToHash("0x2"), common.Hash{0x3}, common.Hash{0x3}, + }, + { + common.HexToHash("0x3"), common.Hash{0x3}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0x1"), common.Hash{0x2}, common.Hash{0x2}, + }, + { + common.HexToHash("0x2"), common.Hash{0x2}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0x3"), common.Hash{0x2}, common.Hash{0x1}, // not found + }, + /* + lookup storage slot from the bottom + */ + { + common.HexToHash("0x1"), common.Hash{0x1}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0x2"), common.Hash{0x1}, common.Hash{0x1}, // not found + }, + { + common.HexToHash("0x3"), common.Hash{0x1}, common.Hash{0x1}, // not found + }, + } + for i, c := range cases { + l, err := tr.lookupStorage(common.HexToHash("0xa"), c.storage, c.state) + if err != nil { + t.Fatalf("%d: %v", i, err) + } + if l.rootHash() != c.expect { + t.Errorf("Unexpected tiphash, %d, want: %x, got: %x", i, c.expect, l.rootHash()) + } + } + + // Chain: + // C3->C4 (HEAD) + tr.cap(common.Hash{0x4}, 1) + + cases2 := []struct { + storage common.Hash + state common.Hash + expect common.Hash + expectErr error + }{ + { + // unknown storage slot + common.HexToHash("0x4"), common.Hash{0x4}, common.Hash{0x3}, nil, + }, + /* + lookup account from the top + */ + { + common.HexToHash("0x1"), common.Hash{0x4}, common.Hash{0x4}, nil, + }, + { + common.HexToHash("0x2"), common.Hash{0x4}, common.Hash{0x3}, nil, + }, + { + common.HexToHash("0x3"), common.Hash{0x4}, common.Hash{0x4}, nil, + }, + /* + lookup account from the bottom + */ + { + common.HexToHash("0x1"), common.Hash{0x3}, common.Hash{0x3}, nil, + }, + { + common.HexToHash("0x2"), common.Hash{0x3}, common.Hash{0x3}, nil, + }, + { + common.HexToHash("0x3"), common.Hash{0x3}, common.Hash{0x3}, nil, // not found + }, + /* + stale states + */ + { + common.HexToHash("0x1"), common.Hash{0x2}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0x2"), common.Hash{0x2}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0x3"), common.Hash{0x2}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0x1"), common.Hash{0x1}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0x2"), common.Hash{0x1}, common.Hash{}, errSnapshotStale, + }, + { + common.HexToHash("0x3"), common.Hash{0x1}, common.Hash{}, errSnapshotStale, + }, + } + for i, c := range cases2 { + l, err := tr.lookupStorage(common.HexToHash("0xa"), c.storage, c.state) + if c.expectErr != nil { + if !errors.Is(err, c.expectErr) { + t.Fatalf("%d: unexpected error, want %v, got %v", i, c.expectErr, err) + } + } + if c.expectErr == nil { + if err != nil { + t.Fatalf("%d: %v", i, err) + } + if l.rootHash() != c.expect { + t.Errorf("Unexpected tiphash, %d, want: %x, got: %x", i, c.expect, l.rootHash()) + } + } + } +} diff --git a/triedb/pathdb/lookup.go b/triedb/pathdb/lookup.go new file mode 100644 index 0000000000..8b092730f8 --- /dev/null +++ b/triedb/pathdb/lookup.go @@ -0,0 +1,278 @@ +// Copyright 2024 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 . + +package pathdb + +import ( + "fmt" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "golang.org/x/sync/errgroup" +) + +// storageKey returns a key for uniquely identifying the storage slot. +func storageKey(accountHash common.Hash, slotHash common.Hash) [64]byte { + var key [64]byte + copy(key[:32], accountHash[:]) + copy(key[32:], slotHash[:]) + return key +} + +// lookup is an internal structure used to efficiently determine the layer in +// which a state entry resides. +type lookup struct { + // accounts represents the mutation history for specific accounts. + // The key is the account address hash, and the value is a slice + // of **diff layer** IDs indicating where the account was modified, + // with the order from oldest to newest. + accounts map[common.Hash][]common.Hash + + // storages represents the mutation history for specific storage + // slot. The key is the account address hash and the storage key + // hash, the value is a slice of **diff layer** IDs indicating + // where the slot was modified, with the order from oldest to newest. + storages map[[64]byte][]common.Hash + + // descendant is the callback indicating whether the layer with + // given root is a descendant of the one specified by `ancestor`. + descendant func(state common.Hash, ancestor common.Hash) bool +} + +// newLookup initializes the lookup structure. +func newLookup(head layer, descendant func(state common.Hash, ancestor common.Hash) bool) *lookup { + var ( + current = head + layers []layer + ) + for current != nil { + layers = append(layers, current) + current = current.parentLayer() + } + l := &lookup{ + accounts: make(map[common.Hash][]common.Hash), + storages: make(map[[64]byte][]common.Hash), + descendant: descendant, + } + // Apply the diff layers from bottom to top + for i := len(layers) - 1; i >= 0; i-- { + switch diff := layers[i].(type) { + case *diskLayer: + continue + case *diffLayer: + l.addLayer(diff) + } + } + return l +} + +// accountTip traverses the layer list associated with the given account in +// reverse order to locate the first entry that either matches the specified +// stateID or is a descendant of it. +// +// If found, the account data corresponding to the supplied stateID resides +// in that layer. Otherwise, two scenarios are possible: +// +// (a) the account remains unmodified from the current disk layer up to the state +// layer specified by the stateID: fallback to the disk layer for data retrieval, +// (b) or the layer specified by the stateID is stale: reject the data retrieval. +func (l *lookup) accountTip(accountHash common.Hash, stateID common.Hash, base common.Hash) common.Hash { + // Traverse the mutation history from latest to oldest one. Several + // scenarios are possible: + // + // Chain: + // D->C1->C2->C3->C4 (HEAD) + // ->C1'->C2'->C3' + // State: + // x: [C1, C1', C3', C3] + // y: [] + // + // - (x, C4) => C3 + // - (x, C3) => C3 + // - (x, C2) => C1 + // - (x, C3') => C3' + // - (x, C2') => C1' + // - (y, C4) => D + // - (y, C3') => D + // - (y, C0) => null + list := l.accounts[accountHash] + for i := len(list) - 1; i >= 0; i-- { + // If the current state matches the stateID, or the requested state is a + // descendant of it, return the current state as the most recent one + // containing the modified data. Otherwise, the current state may be ahead + // of the requested one or belong to a different branch. + if list[i] == stateID || l.descendant(stateID, list[i]) { + return list[i] + } + } + // No layer matching the stateID or its descendants was found. Use the + // current disk layer as a fallback. + if base == stateID || l.descendant(stateID, base) { + return base + } + // The layer associated with 'stateID' is not the descendant of the current + // disk layer, it's already stale, return nothing. + return common.Hash{} +} + +// storageTip traverses the layer list associated with the given account and +// slot hash in reverse order to locate the first entry that either matches +// the specified stateID or is a descendant of it. +// +// If found, the storage data corresponding to the supplied stateID resides +// in that layer. Otherwise, two scenarios are possible: +// +// (a) the storage slot remains unmodified from the current disk layer up to +// the state layer specified by the stateID: fallback to the disk layer for +// data retrieval, (b) or the layer specified by the stateID is stale: reject +// the data retrieval. +func (l *lookup) storageTip(accountHash common.Hash, slotHash common.Hash, stateID common.Hash, base common.Hash) common.Hash { + list := l.storages[storageKey(accountHash, slotHash)] + for i := len(list) - 1; i >= 0; i-- { + // If the current state matches the stateID, or the requested state is a + // descendant of it, return the current state as the most recent one + // containing the modified data. Otherwise, the current state may be ahead + // of the requested one or belong to a different branch. + if list[i] == stateID || l.descendant(stateID, list[i]) { + return list[i] + } + } + // No layer matching the stateID or its descendants was found. Use the + // current disk layer as a fallback. + if base == stateID || l.descendant(stateID, base) { + return base + } + // The layer associated with 'stateID' is not the descendant of the current + // disk layer, it's already stale, return nothing. + return common.Hash{} +} + +// addLayer traverses the state data retained in the specified diff layer and +// integrates it into the lookup set. +// +// This function assumes that all layers older than the provided one have already +// been processed, ensuring that layers are processed strictly in a bottom-to-top +// order. +func (l *lookup) addLayer(diff *diffLayer) { + defer func(now time.Time) { + lookupAddLayerTimer.UpdateSince(now) + }(time.Now()) + + var ( + wg sync.WaitGroup + state = diff.rootHash() + ) + wg.Add(1) + go func() { + defer wg.Done() + for accountHash := range diff.states.accountData { + list, exists := l.accounts[accountHash] + if !exists { + list = make([]common.Hash, 0, 16) // TODO(rjl493456442) use sync pool + } + list = append(list, state) + l.accounts[accountHash] = list + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + for accountHash, slots := range diff.states.storageData { + for slotHash := range slots { + key := storageKey(accountHash, slotHash) + list, exists := l.storages[key] + if !exists { + list = make([]common.Hash, 0, 16) // TODO(rjl493456442) use sync pool + } + list = append(list, state) + l.storages[key] = list + } + } + }() + wg.Wait() +} + +// removeFromList removes the specified element from the provided list. +// It returns a flag indicating whether the element was found and removed. +func removeFromList(list []common.Hash, element common.Hash) (bool, []common.Hash) { + // Traverse the list from oldest to newest to quickly locate the element. + for i := 0; i < len(list); i++ { + if list[i] == element { + if i != 0 { + list = append(list[:i], list[i+1:]...) + } else { + // Remove the first element by shifting the slice forward. + // Pros: zero-copy. + // Cons: may retain large backing array, causing memory leaks. + // Mitigation: release the array if capacity exceeds threshold. + list = list[1:] + if cap(list) > 1024 { + list = append(make([]common.Hash, 0, len(list)), list...) + } + } + return true, list + } + } + return false, nil +} + +// removeLayer traverses the state data retained in the specified diff layer and +// unlink them from the lookup set. +func (l *lookup) removeLayer(diff *diffLayer) error { + defer func(now time.Time) { + lookupRemoveLayerTimer.UpdateSince(now) + }(time.Now()) + + var ( + eg errgroup.Group + state = diff.rootHash() + ) + eg.Go(func() error { + for accountHash := range diff.states.accountData { + found, list := removeFromList(l.accounts[accountHash], state) + if !found { + return fmt.Errorf("account lookup is not found, %x, state: %x", accountHash, state) + } + if len(list) != 0 { + l.accounts[accountHash] = list + } else { + delete(l.accounts, accountHash) + } + } + return nil + }) + + eg.Go(func() error { + for accountHash, slots := range diff.states.storageData { + for slotHash := range slots { + key := storageKey(accountHash, slotHash) + found, list := removeFromList(l.storages[key], state) + if !found { + return fmt.Errorf("storage lookup is not found, %x %x, state: %x", accountHash, slotHash, state) + } + if len(list) != 0 { + l.storages[key] = list + } else { + delete(l.storages, key) + } + } + } + return nil + }) + return eg.Wait() +} diff --git a/triedb/pathdb/metrics.go b/triedb/pathdb/metrics.go index 502c34fc62..6d40c5713b 100644 --- a/triedb/pathdb/metrics.go +++ b/triedb/pathdb/metrics.go @@ -72,6 +72,9 @@ var ( historyBuildTimeMeter = metrics.NewRegisteredResettingTimer("pathdb/history/time", nil) historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil) historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil) + + lookupAddLayerTimer = metrics.NewRegisteredResettingTimer("pathdb/lookup/add/time", nil) + lookupRemoveLayerTimer = metrics.NewRegisteredResettingTimer("pathdb/lookup/remove/time", nil) ) // Metrics in generation diff --git a/triedb/pathdb/reader.go b/triedb/pathdb/reader.go index 30f75d1058..bc72db34e3 100644 --- a/triedb/pathdb/reader.go +++ b/triedb/pathdb/reader.go @@ -17,6 +17,7 @@ package pathdb import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -50,8 +51,10 @@ func (loc *nodeLoc) string() string { // reader implements the database.NodeReader interface, providing the functionalities to // retrieve trie nodes by wrapping the internal state layer. type reader struct { - layer layer + db *Database + state common.Hash noHashCheck bool + layer layer } // Node implements database.NodeReader interface, retrieving the node with specified @@ -94,7 +97,23 @@ func (r *reader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, // - the returned account data is not a copy, please don't modify it // - no error will be returned if the requested account is not found in database func (r *reader) AccountRLP(hash common.Hash) ([]byte, error) { - return r.layer.account(hash, 0) + l, err := r.db.tree.lookupAccount(hash, r.state) + if err != nil { + return nil, err + } + // If the located layer is stale, fall back to the slow path to retrieve + // the account data. This is an edge case where the located layer is the + // disk layer (e.g., the requested account was not changed in all the diff + // layers), and it becomes stale within a very short time window. + // + // This fallback mechanism is essential, because the traversal starts from + // the entry point layer and goes down, the staleness of the disk layer does + // not affect the result unless the entry point layer is also stale. + blob, err := l.account(hash, 0) + if errors.Is(err, errSnapshotStale) { + return r.layer.account(hash, 0) + } + return blob, err } // Account directly retrieves the account associated with a particular hash in @@ -105,7 +124,7 @@ func (r *reader) AccountRLP(hash common.Hash) ([]byte, error) { // - the returned account object is safe to modify // - no error will be returned if the requested account is not found in database func (r *reader) Account(hash common.Hash) (*types.SlimAccount, error) { - blob, err := r.layer.account(hash, 0) + blob, err := r.AccountRLP(hash) if err != nil { return nil, err } @@ -127,7 +146,23 @@ func (r *reader) Account(hash common.Hash) (*types.SlimAccount, error) { // - the returned storage data is not a copy, please don't modify it // - no error will be returned if the requested slot is not found in database func (r *reader) Storage(accountHash, storageHash common.Hash) ([]byte, error) { - return r.layer.storage(accountHash, storageHash, 0) + l, err := r.db.tree.lookupStorage(accountHash, storageHash, r.state) + if err != nil { + return nil, err + } + // If the located layer is stale, fall back to the slow path to retrieve + // the storage data. This is an edge case where the located layer is the + // disk layer (e.g., the requested account was not changed in all the diff + // layers), and it becomes stale within a very short time window. + // + // This fallback mechanism is essential, because the traversal starts from + // the entry point layer and goes down, the staleness of the disk layer does + // not affect the result unless the entry point layer is also stale. + blob, err := l.storage(accountHash, storageHash, 0) + if errors.Is(err, errSnapshotStale) { + return r.layer.storage(accountHash, storageHash, 0) + } + return blob, err } // NodeReader retrieves a layer belonging to the given state root. @@ -136,7 +171,12 @@ func (db *Database) NodeReader(root common.Hash) (database.NodeReader, error) { if layer == nil { return nil, fmt.Errorf("state %#x is not available", root) } - return &reader{layer: layer, noHashCheck: db.isVerkle}, nil + return &reader{ + db: db, + state: root, + noHashCheck: db.isVerkle, + layer: layer, + }, nil } // StateReader returns a reader that allows access to the state data associated @@ -146,5 +186,9 @@ func (db *Database) StateReader(root common.Hash) (database.StateReader, error) if layer == nil { return nil, fmt.Errorf("state %#x is not available", root) } - return &reader{layer: layer}, nil + return &reader{ + db: db, + state: root, + layer: layer, + }, nil } From 1695182b55f49df20bb3046a0bbc1ca2665f551d Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 17:51:47 +0200 Subject: [PATCH 057/365] .gitea: adjust cron schedule (#31915) This should make the scheduled build actually run. --- .gitea/workflows/release-cron.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/release-cron.yml b/.gitea/workflows/release-cron.yml index 3a03d0ef14..11798630dd 100644 --- a/.gitea/workflows/release-cron.yml +++ b/.gitea/workflows/release-cron.yml @@ -2,7 +2,7 @@ name: Release Builds (cron) on: schedule: - cron: '0 0 * * *' + - cron: '0 16 * * *' jobs: azure-cleanup: From 0110b659c1db7612664e7fdfadbe005796992931 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 18:24:43 +0200 Subject: [PATCH 058/365] .gitea: add env to scheduled builds (#31918) --- .gitea/workflows/release-cron.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitea/workflows/release-cron.yml b/.gitea/workflows/release-cron.yml index 11798630dd..383c9887d6 100644 --- a/.gitea/workflows/release-cron.yml +++ b/.gitea/workflows/release-cron.yml @@ -3,6 +3,7 @@ name: Release Builds (cron) on: schedule: - cron: '0 16 * * *' + workflow_dispatch: jobs: azure-cleanup: @@ -17,6 +18,8 @@ jobs: cache: false - name: Run cleanup script + env: + AZURE_BLOBSTORE_TOKEN: "{{ secrets.AZURE_BLOBSTORE_TOKEN }}" run: | go run build/ci.go purge -store gethstore/builds -days 14 @@ -37,6 +40,9 @@ jobs: apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot - name: Run ci.go + env: + DOCKER_HUB_USERNAME: "{{ secrets.DOCKER_HUB_USERNAME }}" + DOCKER_HUB_PASSWORD: "{{ secrets.DOCKER_HUB_PASSWORD }}" run: | 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 " From 25f6206137bcfd260a577396e34fa3e9bdafc85e Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 19:01:33 +0200 Subject: [PATCH 059/365] .gitea: port more builds from travis and fix PPA env (#31919) --- .gitea/workflows/release-cron.yml | 4 +- .gitea/workflows/release.yml | 70 ++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/release-cron.yml b/.gitea/workflows/release-cron.yml index 383c9887d6..4f586f5284 100644 --- a/.gitea/workflows/release-cron.yml +++ b/.gitea/workflows/release-cron.yml @@ -41,8 +41,8 @@ jobs: - name: Run ci.go env: - DOCKER_HUB_USERNAME: "{{ secrets.DOCKER_HUB_USERNAME }}" - DOCKER_HUB_PASSWORD: "{{ secrets.DOCKER_HUB_PASSWORD }}" + PPA_SIGNING_KEY: "{{ secrets.PPA_SIGNING_KEY }}" + PPA_SSH_KEY: "{{ secrets.PPA_SSH_KEY }}" run: | 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 " diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index a91bebda7f..29154c6ef0 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -5,7 +5,7 @@ on: branches: [ master ] jobs: - linux: + linux-intel: name: Linux Build runs-on: ubuntu-latest steps: @@ -17,13 +17,68 @@ jobs: go-version: 1.24 cache: false - - name: display environment + - name: Run build (amd64) + env: + LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" run: | - env + go run build/ci.go install -arch amd64 -dlgo + go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - name: Run build + - name: Run build (386) + env: + LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" run: | - go run build/ci.go install + apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib + go run build/ci.go install -arch 386 -dlgo + go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + + linux-arm: + name: Linux Build (arm) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.24 + cache: false + + - name: Set up cross toolchain + run: | + apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross + ln -s /usr/include/asm-generic /usr/include/asm + + - name: Run build (arm64) + env: + LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + run: | + go run build/ci.go install -dlgo -arch arm64 -cc arm-linux-gnueabi-gcc + go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + + - name: Run build (armv5) + env: + GOARM: "5" + LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + run: | + go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + + - name: Run build (armv6) + env: + GOARM: "6" + LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + run: | + go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + + - name: Run build (armv7) + env: + GOARM: "7" + LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + run: | + go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds docker: name: Docker Image @@ -44,5 +99,8 @@ jobs: cache: false - name: Run docker build + env: + DOCKER_HUB_USERNAME: "{{ secrets.DOCKER_HUB_USERNAME }}" + DOCKER_HUB_PASSWORD: "{{ secrets.DOCKER_HUB_PASSWORD }}" run: | - go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 + go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 -upload From e817a569fb9b84e252316a29ab491d7b76ce0ad8 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 20:14:48 +0200 Subject: [PATCH 060/365] .gitea: fix secrets passing (#31920) --- .gitea/workflows/release-cron.yml | 6 +++--- .gitea/workflows/release.yml | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.gitea/workflows/release-cron.yml b/.gitea/workflows/release-cron.yml index 4f586f5284..735404129a 100644 --- a/.gitea/workflows/release-cron.yml +++ b/.gitea/workflows/release-cron.yml @@ -19,7 +19,7 @@ jobs: - name: Run cleanup script env: - AZURE_BLOBSTORE_TOKEN: "{{ secrets.AZURE_BLOBSTORE_TOKEN }}" + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} run: | go run build/ci.go purge -store gethstore/builds -days 14 @@ -41,8 +41,8 @@ jobs: - name: Run ci.go env: - PPA_SIGNING_KEY: "{{ secrets.PPA_SIGNING_KEY }}" - PPA_SSH_KEY: "{{ secrets.PPA_SSH_KEY }}" + PPA_SIGNING_KEY: ${{ secrets.PPA_SIGNING_KEY }} + PPA_SSH_KEY: ${{ secrets.PPA_SSH_KEY }} run: | 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 " diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 29154c6ef0..7675c75e16 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -19,18 +19,18 @@ jobs: - name: Run build (amd64) env: - LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | go run build/ci.go install -arch amd64 -dlgo - go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - name: Run build (386) env: - LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib go run build/ci.go install -arch 386 -dlgo - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds linux-arm: name: Linux Build (arm) @@ -51,34 +51,34 @@ jobs: - name: Run build (arm64) env: - LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | go run build/ci.go install -dlgo -arch arm64 -cc arm-linux-gnueabi-gcc - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - name: Run build (armv5) env: GOARM: "5" - LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - name: Run build (armv6) env: GOARM: "6" - LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - name: Run build (armv7) env: GOARM: "7" - LINUX_SIGNING_KEY: "{{ secrets.LINUX_SIGNING_KEY }}" + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds docker: name: Docker Image @@ -100,7 +100,7 @@ jobs: - name: Run docker build env: - DOCKER_HUB_USERNAME: "{{ secrets.DOCKER_HUB_USERNAME }}" - DOCKER_HUB_PASSWORD: "{{ secrets.DOCKER_HUB_PASSWORD }}" + DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} + DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }} run: | go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 -upload From 31d898d586b6388ce47c1965eae8f2c7114d194f Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 22:40:26 +0200 Subject: [PATCH 061/365] .gitea: fix apt update (#31921) --- .gitea/workflows/release-cron.yml | 1 + .gitea/workflows/release.yml | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/.gitea/workflows/release-cron.yml b/.gitea/workflows/release-cron.yml index 735404129a..1a8eea2890 100644 --- a/.gitea/workflows/release-cron.yml +++ b/.gitea/workflows/release-cron.yml @@ -37,6 +37,7 @@ jobs: - name: Install deb toolchain run: | + apt-get update apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot - name: Run ci.go diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 7675c75e16..8efd453642 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -17,20 +17,32 @@ jobs: go-version: 1.24 cache: false - - name: Run build (amd64) + - name: Install cross toolchain + run: | + apt-get update + apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib + + - name: Build (amd64) + run: | + go run build/ci.go install -arch amd64 -dlgo + + - name: Create archive (amd64) env: LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | - go run build/ci.go install -arch amd64 -dlgo go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds + rm -f build/bin/* + + - name: Build (386) + run: | + go run build/ci.go install -arch 386 -dlgo - - name: Run build (386) + - name: Create archive (386) env: LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} run: | - apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib - go run build/ci.go install -arch 386 -dlgo go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds + rm -f build/bin/* linux-arm: name: Linux Build (arm) @@ -46,7 +58,8 @@ jobs: - name: Set up cross toolchain run: | - apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross + apt-get update + apt-get -yq --no-install-suggests --no-install-recommends install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross ln -s /usr/include/asm-generic /usr/include/asm - name: Run build (arm64) From b065aa6740e4ed109b5e3efd9abadb12b439870c Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 22:57:58 +0200 Subject: [PATCH 062/365] .gitea: fix archive uploads and run PPA upload on release push (#31922) --- .gitea/workflows/release-azure-cleanup.yml | 22 ++++++ .../{release-cron.yml => release-ppa.yml} | 33 +++------ .gitea/workflows/release.yml | 69 +++++++++++++------ 3 files changed, 80 insertions(+), 44 deletions(-) create mode 100644 .gitea/workflows/release-azure-cleanup.yml rename .gitea/workflows/{release-cron.yml => release-ppa.yml} (73%) diff --git a/.gitea/workflows/release-azure-cleanup.yml b/.gitea/workflows/release-azure-cleanup.yml new file mode 100644 index 0000000000..da2400ee26 --- /dev/null +++ b/.gitea/workflows/release-azure-cleanup.yml @@ -0,0 +1,22 @@ +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + azure-cleanup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.24 + cache: false + + - name: Run cleanup script + run: | + go run build/ci.go purge -store gethstore/builds -days 14 + env: + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} diff --git a/.gitea/workflows/release-cron.yml b/.gitea/workflows/release-ppa.yml similarity index 73% rename from .gitea/workflows/release-cron.yml rename to .gitea/workflows/release-ppa.yml index 1a8eea2890..23bffe773d 100644 --- a/.gitea/workflows/release-cron.yml +++ b/.gitea/workflows/release-ppa.yml @@ -1,30 +1,14 @@ -name: Release Builds (cron) - on: schedule: - cron: '0 16 * * *' + push: + branches: + - "release/*" workflow_dispatch: jobs: - azure-cleanup: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: 1.24 - cache: false - - - name: Run cleanup script - env: - AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} - run: | - go run build/ci.go purge -store gethstore/builds -days 14 - ppa: - name: PPA Upload (master) + name: PPA Upload runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -40,10 +24,13 @@ jobs: apt-get update apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot + - name: Add launchpad to known_hosts + run: | + echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts + - name: Run ci.go + run: | + go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " env: PPA_SIGNING_KEY: ${{ secrets.PPA_SIGNING_KEY }} PPA_SSH_KEY: ${{ secrets.PPA_SSH_KEY }} - run: | - 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 " diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 8efd453642..10e0f7aa7f 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -1,8 +1,8 @@ -name: Release Builds (push) - on: push: - branches: [ master ] + branches: + - "master" + - "release/*" jobs: linux-intel: @@ -26,23 +26,25 @@ jobs: run: | go run build/ci.go install -arch amd64 -dlgo - - name: Create archive (amd64) - env: - LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + - name: Create/upload archive (amd64) run: | go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds rm -f build/bin/* + env: + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} - name: Build (386) run: | go run build/ci.go install -arch 386 -dlgo - - name: Create archive (386) - env: - LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + - name: Create/upload archive (386) run: | go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds rm -f build/bin/* + env: + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} linux-arm: name: Linux Build (arm) @@ -56,42 +58,67 @@ jobs: go-version: 1.24 cache: false - - name: Set up cross toolchain + - name: Install cross toolchain run: | apt-get update apt-get -yq --no-install-suggests --no-install-recommends install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross ln -s /usr/include/asm-generic /usr/include/asm - - name: Run build (arm64) - env: - LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + - name: Build (arm64) run: | go run build/ci.go install -dlgo -arch arm64 -cc arm-linux-gnueabi-gcc + + - name: Create/upload archive (arm64) + run: | go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds + rm -fr build/bin/* + env: + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} + + - name: Run build (arm5) + run: | + go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc + env: + GOARM: "5" - - name: Run build (armv5) + - name: Create/upload archive (arm5) + run: | + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds env: GOARM: "5" LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} + + - name: Run build (arm6) run: | go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds + env: + GOARM: "6" - - name: Run build (armv6) + - name: Create/upload archive (arm6) + run: | + go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds + rm -fr build/bin/* env: GOARM: "6" LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} + + - name: Run build (arm7) run: | go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - - - name: Run build (armv7) env: GOARM: "7" - LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + + - name: Create/upload archive (arm7) run: | - go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds + rm -fr build/bin/* + env: + GOARM: "7" + LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} + AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} docker: name: Docker Image From 3524499d558ce85b51d5e803154e01b9210b3913 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 23:16:51 +0200 Subject: [PATCH 063/365] .gitea: fix arm64 build (#31923) --- .gitea/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 10e0f7aa7f..f1637bd5ae 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -66,7 +66,7 @@ jobs: - name: Build (arm64) run: | - go run build/ci.go install -dlgo -arch arm64 -cc arm-linux-gnueabi-gcc + go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc - name: Create/upload archive (arm64) run: | From e9e4e8b05ae99c8f4e22ae2e6db4f75ce5b848b6 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 28 May 2025 23:19:13 +0200 Subject: [PATCH 064/365] .gitea: run release build on tag push (#31924) --- .gitea/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index f1637bd5ae..04e724ccf4 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -2,7 +2,8 @@ on: push: branches: - "master" - - "release/*" + tags: + - "v*" jobs: linux-intel: From d821f7f297259b2ed5ab0d3c99c0e4aca9663ac8 Mon Sep 17 00:00:00 2001 From: Arya Nair Date: Thu, 29 May 2025 09:50:39 +0530 Subject: [PATCH 065/365] cmd/geth, cmd/utils: log prefunded account/key in ephemeral development mode (#31898) This PR modifies the disclaimer/banner that is printed when starting up Geth in dev mode: * if the client is spun up in ephemeral dev mode with a keystore override, the address of the first (prefunded) account is printed. * if the client is spun up in ephemeral mode without a keystore override, the genesis allocation contains a single static prefunded EOA account. It's address and private key are logged. * the banner is printed at the end of client initialization to make it more prominent. Previously, it was logged towards the beginning of client initialization and subsequent logging from startup filled the terminal, pushing it out of view of the user. Other change is that we now use a static prefunded dev account instead of generating a random one when instantiating a new dev mode chain. This is an example of what the banner looks like: ``` WARN [05-28|23:05:16.475] You are running Geth in --dev mode. Please note the following: WARN [05-28|23:05:16.475] WARN [05-28|23:05:16.475] 1. This mode is only intended for fast, iterative development without assumptions on WARN [05-28|23:05:16.475] security or persistence. WARN [05-28|23:05:16.475] 2. The database is created in memory unless specified otherwise. Therefore, shutting down WARN [05-28|23:05:16.475] your computer or losing power will wipe your entire block data and chain state for WARN [05-28|23:05:16.475] your dev environment. WARN [05-28|23:05:16.475] 3. A random, pre-allocated developer account will be available and unlocked as WARN [05-28|23:05:16.475] eth.coinbase, which can be used for testing. The random dev account is temporary, WARN [05-28|23:05:16.475] stored on a ramdisk, and will be lost if your machine is restarted. WARN [05-28|23:05:16.475] 4. Mining is enabled by default. However, the client will only seal blocks if transactions WARN [05-28|23:05:16.475] are pending in the mempool. The miner's minimum accepted gas price is 1. WARN [05-28|23:05:16.475] 5. Networking is disabled; there is no listen-address, the maximum number of peers is set WARN [05-28|23:05:16.475] to 0, and discovery is disabled. WARN [05-28|23:05:16.475] WARN [05-28|23:05:16.475] WARN [05-28|23:05:16.475] Running in ephemeral mode. The following account has been prefunded in the genesis: WARN [05-28|23:05:16.475] WARN [05-28|23:05:16.475] Account WARN [05-28|23:05:16.475] ------------------ WARN [05-28|23:05:16.475] 0x71562b71999873db5b286df957af199ec94617f7 (10^49 ETH) WARN [05-28|23:05:16.475] WARN [05-28|23:05:16.475] Private Key WARN [05-28|23:05:16.475] ------------------ WARN [05-28|23:05:16.475] 0xb71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291 WARN [05-28|23:05:16.475] ``` closes #31796 --------- Co-authored-by: jwasinger --- cmd/geth/config.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ cmd/geth/main.go | 18 ------------------ cmd/utils/flags.go | 20 +++++++++++++++----- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 4215403234..3eb2b6dd37 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -36,6 +36,7 @@ import ( "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/crypto" "github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/flags" @@ -180,6 +181,45 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { return stack, cfg } +// constructs the disclaimer text block which will be printed in the logs upon +// startup when Geth is running in dev mode. +func constructDevModeBanner(ctx *cli.Context, cfg gethConfig) string { + devModeBanner := `You are running Geth in --dev mode. Please note the following: + + 1. This mode is only intended for fast, iterative development without assumptions on + security or persistence. + 2. The database is created in memory unless specified otherwise. Therefore, shutting down + your computer or losing power will wipe your entire block data and chain state for + your dev environment. + 3. A random, pre-allocated developer account will be available and unlocked as + eth.coinbase, which can be used for testing. The random dev account is temporary, + stored on a ramdisk, and will be lost if your machine is restarted. + 4. Mining is enabled by default. However, the client will only seal blocks if transactions + are pending in the mempool. The miner's minimum accepted gas price is 1. + 5. Networking is disabled; there is no listen-address, the maximum number of peers is set + to 0, and discovery is disabled. +` + if !ctx.IsSet(utils.DataDirFlag.Name) { + devModeBanner += fmt.Sprintf(` + + Running in ephemeral mode. The following account has been prefunded in the genesis: + + Account + ------------------ + 0x%x (10^49 ETH) +`, cfg.Eth.Miner.PendingFeeRecipient) + if cfg.Eth.Miner.PendingFeeRecipient == utils.DeveloperAddr { + devModeBanner += fmt.Sprintf(` + Private Key + ------------------ + 0x%x +`, crypto.FromECDSA(utils.DeveloperKey)) + } + } + + return devModeBanner +} + // makeFullNode loads geth configuration and creates the Ethereum backend. func makeFullNode(ctx *cli.Context) *node.Node { stack, cfg := makeConfigNode(ctx) @@ -239,6 +279,11 @@ func makeFullNode(ctx *cli.Context) *node.Node { } catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon) stack.RegisterLifecycle(simBeacon) + + banner := constructDevModeBanner(ctx, cfg) + for _, line := range strings.Split(banner, "\n") { + log.Warn(line) + } } else if ctx.IsSet(utils.BeaconApiFlag.Name) { // Start blsync mode. srv := rpc.NewServer() diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 733c9cf230..289af90828 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -294,24 +294,6 @@ func prepare(ctx *cli.Context) { case ctx.IsSet(utils.HoodiFlag.Name): log.Info("Starting Geth on Hoodi testnet...") - case ctx.IsSet(utils.DeveloperFlag.Name): - log.Info("Starting Geth in ephemeral dev mode...") - log.Warn(`You are running Geth in --dev mode. Please note the following: - - 1. This mode is only intended for fast, iterative development without assumptions on - security or persistence. - 2. The database is created in memory unless specified otherwise. Therefore, shutting down - your computer or losing power will wipe your entire block data and chain state for - your dev environment. - 3. A random, pre-allocated developer account will be available and unlocked as - eth.coinbase, which can be used for testing. The random dev account is temporary, - stored on a ramdisk, and will be lost if your machine is restarted. - 4. Mining is enabled by default. However, the client will only seal blocks if transactions - are pending in the mempool. The miner's minimum accepted gas price is 1. - 5. Networking is disabled; there is no listen-address, the maximum number of peers is set - to 0, and discovery is disabled. -`) - case !ctx.IsSet(utils.NetworkIdFlag.Name): log.Info("Starting Geth on Ethereum mainnet...") } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 81c4172a53..60a2cc13f1 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -984,6 +984,12 @@ var ( } ) +// default account to prefund when running Geth in dev mode +var ( + DeveloperKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + DeveloperAddr = crypto.PubkeyToAddress(DeveloperKey.PublicKey) +) + // MakeDataDir retrieves the currently requested data directory, terminating // if none (or the empty string) is specified. If the node is starting a testnet, // then a subdirectory of the specified datadir will be used. @@ -1769,9 +1775,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } else if accs := ks.Accounts(); len(accs) > 0 { developer = ks.Accounts()[0] } else { - developer, err = ks.NewAccount(passphrase) + developer, err = ks.ImportECDSA(DeveloperKey, passphrase) if err != nil { - Fatalf("Failed to create developer account: %v", err) + Fatalf("Failed to import developer account: %v", err) } } // Make sure the address is configured as fee recipient, otherwise @@ -1786,14 +1792,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } log.Info("Using developer account", "address", developer.Address) - // Create a new developer genesis block or reuse existing one + // configure default developer genesis which will be used unless a + // datadir is specified and a chain is preexisting at that location. cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), &developer.Address) + + // If a datadir is specified, ensure that any preexisting chain in that location + // has a configuration that is compatible with dev mode: it must be merged at genesis. if ctx.IsSet(DataDirFlag.Name) { chaindb := tryMakeReadOnlyDatabase(ctx, stack) if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) { - cfg.Genesis = nil // fallback to db content + // signal fallback to preexisting chain on disk + cfg.Genesis = nil - //validate genesis has PoS enabled in block 0 genesis, err := core.ReadGenesis(chaindb) if err != nil { Fatalf("Could not read genesis from database: %v", err) From 8712a2cdbab8a6c23b6b7a6e379f35227490f011 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 29 May 2025 12:23:38 +0200 Subject: [PATCH 066/365] .travis.yml: remove master branch push builds (#31927) Release artefact building has been migrated to another system (Gitea), so we can finally stop using Travis CI. However, in order to have a fail-safe for the release, I'm leaving the config in and it will still trigger builds on Travis for tagged releases. That way, if our new system fails to work for the next release, we will still have the option of using Travis. --- .travis.yml | 65 +++++++++++++++-------------------------------------- 1 file changed, 18 insertions(+), 47 deletions(-) diff --git a/.travis.yml b/.travis.yml index 43f8ced19c..28d934c655 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ jobs: include: # This builder create and push the Docker images for all architectures - stage: build - if: type = push + if: type = push && tag ~= /^v[0-9]/ os: linux arch: amd64 dist: focal @@ -21,9 +21,25 @@ jobs: script: - go run build/ci.go dockerx -platform "linux/amd64,linux/arm64,linux/riscv64" -hub ethereum/client-go -upload + # This builder does the Ubuntu PPA nightly uploads + - stage: build + if: type = push && tag ~= /^v[0-9]/ + os: linux + dist: focal + go: 1.24.x + env: + - ubuntu-ppa + git: + submodules: false # avoid cloning ethereum/tests + before_install: + - sudo -E apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot + 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 " + # This builder does the Linux Azure uploads - stage: build - if: type = push + if: type = push && tag ~= /^v[0-9]/ os: linux dist: focal sudo: required @@ -56,40 +72,6 @@ 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 - # These builders run the tests - - stage: build - if: type = push - os: linux - arch: amd64 - dist: focal - go: 1.24.x - script: - - travis_wait 45 go run build/ci.go test $TEST_PACKAGES - - - stage: build - if: type = push - os: linux - dist: focal - go: 1.23.x - script: - - travis_wait 45 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: focal - go: 1.24.x - env: - - ubuntu-ppa - git: - submodules: false # avoid cloning ethereum/tests - before_install: - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot - 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 " - # This builder does the Azure archive purges to avoid accumulating junk - stage: build if: type = cron @@ -102,14 +84,3 @@ jobs: submodules: false # avoid cloning ethereum/tests script: - go run build/ci.go purge -store gethstore/builds -days 14 - - # This builder executes race tests - - stage: build - if: type = cron - os: linux - dist: focal - go: 1.24.x - env: - - racetests - script: - - travis_wait 60 go run build/ci.go test -race $TEST_PACKAGES From 2a1784baef0e9d0c0641bc97d1a3478048de5c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Irmak?= Date: Thu, 29 May 2025 13:26:50 +0300 Subject: [PATCH 067/365] go.mod: bump flock package version (#31909) The newer version has a stub implementation for unsupported targets, which allows us to compile to more exotic targets. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d27af647ec..6c192c85d7 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/fjl/gencodec v0.1.0 github.com/fsnotify/fsnotify v1.6.0 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff - github.com/gofrs/flock v0.8.1 + github.com/gofrs/flock v0.12.1 github.com/golang-jwt/jwt/v4 v4.5.1 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/gofuzz v1.2.0 diff --git a/go.sum b/go.sum index 200b3725ea..c91e349656 100644 --- a/go.sum +++ b/go.sum @@ -144,8 +144,8 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyL github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= From 99c0ed11547a0ac1a4527c390cd04da9b9214368 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 2 Jun 2025 13:00:58 +0200 Subject: [PATCH 068/365] .gitea: modify scheduled workflow times (#31946) --- .gitea/workflows/release-azure-cleanup.yml | 2 +- .gitea/workflows/release-ppa.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/release-azure-cleanup.yml b/.gitea/workflows/release-azure-cleanup.yml index da2400ee26..311b2196bb 100644 --- a/.gitea/workflows/release-azure-cleanup.yml +++ b/.gitea/workflows/release-azure-cleanup.yml @@ -1,6 +1,6 @@ on: schedule: - - cron: '0 0 * * *' + - cron: '0 14 * * *' workflow_dispatch: jobs: diff --git a/.gitea/workflows/release-ppa.yml b/.gitea/workflows/release-ppa.yml index 23bffe773d..6c0631dc99 100644 --- a/.gitea/workflows/release-ppa.yml +++ b/.gitea/workflows/release-ppa.yml @@ -1,6 +1,6 @@ on: schedule: - - cron: '0 16 * * *' + - cron: '0 15 * * *' push: branches: - "release/*" From c87b856c1a7daff56b46be70cdb7092adc519b7c Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 2 Jun 2025 16:11:19 +0200 Subject: [PATCH 069/365] eth: return null for not-found in BlockByNumberOrHash (#31949) This changes the API backend to return null for not-found blocks. This behavior is required by the RPC When `BlockByNumberOrHash` always returned an error for this case ever since being added in https://github.com/ethereum/go-ethereum/pull/19491. The backend method has a couple of call sites, and all of them handle a `nil` block result because `BlockByNumber` returns `nil` for not-found. The only case where this makes a real difference is for `eth_getBlockReceipts`, which was changed in #31361 to actually forward the error from `BlockByNumberOrHash` to the caller. --- eth/api_backend.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eth/api_backend.go b/eth/api_backend.go index 57f5a50837..8ec19308f9 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -196,7 +196,9 @@ func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash r if hash, ok := blockNrOrHash.Hash(); ok { header := b.eth.blockchain.GetHeaderByHash(hash) if header == nil { - return nil, errors.New("header for hash not found") + // Return 'null' and no error if block is not found. + // This behavior is required by RPC spec. + return nil, nil } if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { return nil, errors.New("hash is not currently canonical") From a7d9b52eafd8242d6e015dea0903d78f717bf8b2 Mon Sep 17 00:00:00 2001 From: Sina M <1591639+s1na@users.noreply.github.com> Date: Tue, 3 Jun 2025 10:47:38 +0200 Subject: [PATCH 070/365] core/rawdb: integrate eradb backend for RPC (#31604) This implements a backing store for chain history based on era1 files. The new store is integrated with the freezer. Queries for blocks and receipts below the current freezer tail are handled by the era store. --------- Co-authored-by: Gary Rong Co-authored-by: Felix Lange Co-authored-by: lightclient --- cmd/geth/chaincmd.go | 8 +- cmd/utils/flags.go | 19 +- cmd/utils/history_test.go | 2 +- common/lru/basiclru.go | 17 +- core/blockchain_repair_test.go | 8 +- core/blockchain_sethead_test.go | 2 +- core/blockchain_snapshot_test.go | 4 +- core/blockchain_test.go | 22 +- core/rawdb/accessors_chain_test.go | 8 +- core/rawdb/ancienttest/testsuite.go | 21 -- core/rawdb/chain_freezer.go | 110 +++++- core/rawdb/database.go | 51 ++- core/rawdb/eradb/eradb.go | 345 ++++++++++++++++++ core/rawdb/eradb/eradb_test.go | 103 ++++++ .../testdata/sepolia-00000-643a00f7.era1 | Bin 0 -> 3267454 bytes .../testdata/sepolia-00021-b8814b14.era1 | Bin 0 -> 3733097 bytes core/rawdb/freezer.go | 14 +- core/rawdb/freezer_memory.go | 19 - core/rawdb/freezer_resettable.go | 9 - core/rawdb/freezer_table.go | 6 - core/rawdb/freezer_test.go | 6 - core/rawdb/table.go | 6 - core/txindexer_test.go | 6 +- eth/backend.go | 9 +- eth/downloader/downloader_test.go | 2 +- eth/ethconfig/config.go | 1 + eth/ethconfig/gen_config.go | 6 + ethdb/database.go | 4 - ethdb/remotedb/remotedb.go | 7 - internal/era/era.go | 56 ++- internal/era/era_test.go | 25 +- node/database.go | 70 ++-- node/node.go | 75 ++-- triedb/pathdb/database_test.go | 2 +- 34 files changed, 773 insertions(+), 270 deletions(-) create mode 100644 core/rawdb/eradb/eradb.go create mode 100644 core/rawdb/eradb/eradb_test.go create mode 100644 core/rawdb/eradb/testdata/sepolia-00000-643a00f7.era1 create mode 100644 core/rawdb/eradb/testdata/sepolia-00021-b8814b14.era1 diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index dc071725c1..d8488b8268 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -45,6 +45,7 @@ import ( "github.com/ethereum/go-ethereum/internal/era/eradl" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/urfave/cli/v2" ) @@ -277,10 +278,7 @@ func initGenesis(ctx *cli.Context) error { overrides.OverrideVerkle = &v } - chaindb, err := stack.OpenDatabaseWithFreezer("chaindata", 0, 0, ctx.String(utils.AncientFlag.Name), "", false) - if err != nil { - utils.Fatalf("Failed to open database: %v", err) - } + chaindb := utils.MakeChainDatabase(ctx, stack, false) defer chaindb.Close() triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) @@ -317,7 +315,7 @@ func dumpGenesis(ctx *cli.Context) error { // dump whatever already exists in the datadir stack, _ := makeConfigNode(ctx) - db, err := stack.OpenDatabase("chaindata", 0, 0, "", true) + db, err := stack.OpenDatabaseWithOptions("chaindata", node.DatabaseOptions{ReadOnly: true}) if err != nil { return err } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 60a2cc13f1..debec7278d 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -111,6 +111,11 @@ var ( Usage: "Root directory for ancient data (default = inside chaindata)", Category: flags.EthCategory, } + EraFlag = &flags.DirectoryFlag{ + Name: "datadir.era", + Usage: "Root directory for era1 history (default = inside ancient/chain)", + Category: flags.EthCategory, + } MinFreeDiskSpaceFlag = &flags.DirectoryFlag{ Name: "datadir.minfreedisk", Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)", @@ -977,6 +982,7 @@ var ( DatabaseFlags = []cli.Flag{ DataDirFlag, AncientFlag, + EraFlag, RemoteDBFlag, DBEngineFlag, StateSchemeFlag, @@ -1613,6 +1619,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.IsSet(AncientFlag.Name) { cfg.DatabaseFreezer = ctx.String(AncientFlag.Name) } + if ctx.IsSet(EraFlag.Name) { + cfg.DatabaseEra = ctx.String(EraFlag.Name) + } if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) @@ -2082,7 +2091,15 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb. } chainDb = remotedb.New(client) default: - chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "eth/db/chaindata/", readonly) + options := node.DatabaseOptions{ + ReadOnly: readonly, + Cache: cache, + Handles: handles, + AncientsDirectory: ctx.String(AncientFlag.Name), + MetricsNamespace: "eth/db/chaindata/", + EraDirectory: ctx.String(EraFlag.Name), + } + chainDb, err = stack.OpenDatabaseWithOptions("chaindata", options) } if err != nil { Fatalf("Could not open database: %v", err) diff --git a/cmd/utils/history_test.go b/cmd/utils/history_test.go index d3c6bda1c5..be51803f8c 100644 --- a/cmd/utils/history_test.go +++ b/cmd/utils/history_test.go @@ -158,7 +158,7 @@ func TestHistoryImportAndExport(t *testing.T) { } // Now import Era. - db2, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + db2, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) if err != nil { panic(err) } diff --git a/common/lru/basiclru.go b/common/lru/basiclru.go index 7386c77840..154831a796 100644 --- a/common/lru/basiclru.go +++ b/common/lru/basiclru.go @@ -47,30 +47,37 @@ func NewBasicLRU[K comparable, V any](capacity int) BasicLRU[K, V] { // Add adds a value to the cache. Returns true if an item was evicted to store the new item. func (c *BasicLRU[K, V]) Add(key K, value V) (evicted bool) { + _, _, evicted = c.Add3(key, value) + return evicted +} + +// Add3 adds a value to the cache. If an item was evicted to store the new one, it returns the evicted item. +func (c *BasicLRU[K, V]) Add3(key K, value V) (ek K, ev V, evicted bool) { item, ok := c.items[key] if ok { - // Already exists in cache. item.value = value c.items[key] = item c.list.moveToFront(item.elem) - return false + return ek, ev, false } var elem *listElem[K] if c.Len() >= c.cap { elem = c.list.removeLast() - delete(c.items, elem.v) evicted = true + ek = elem.v + ev = c.items[ek].value + delete(c.items, ek) } else { elem = new(listElem[K]) } // Store the new item. - // Note that, if another item was evicted, we re-use its list element here. + // Note that if another item was evicted, we re-use its list element here. elem.v = key c.items[key] = cacheItem[K, V]{elem, value} c.list.pushElem(elem) - return evicted + return ek, ev, evicted } // Contains reports whether the given key exists in the cache. diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index edc8854892..9661cee4c7 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -1769,7 +1769,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } - db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient}) if err != nil { t.Fatalf("Failed to create persistent freezer database: %v", err) } @@ -1854,7 +1854,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s if err != nil { t.Fatalf("Failed to reopen persistent key-value database: %v", err) } - db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + db, err = rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient}) if err != nil { t.Fatalf("Failed to reopen persistent freezer database: %v", err) } @@ -1919,7 +1919,7 @@ func testIssue23496(t *testing.T, scheme string) { if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } - db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient}) if err != nil { t.Fatalf("Failed to create persistent freezer database: %v", err) } @@ -1979,7 +1979,7 @@ func testIssue23496(t *testing.T, scheme string) { if err != nil { t.Fatalf("Failed to reopen persistent key-value database: %v", err) } - db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + db, err = rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient}) if err != nil { t.Fatalf("Failed to reopen persistent freezer database: %v", err) } diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index 51e2a5275f..b094ed3b65 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -1973,7 +1973,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } - db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient}) if err != nil { t.Fatalf("Failed to create persistent freezer database: %v", err) } diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index 23640fe843..e12a0c67c4 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -70,7 +70,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } - db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient}) if err != nil { t.Fatalf("Failed to create persistent freezer database: %v", err) } @@ -265,7 +265,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) { if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } - newdb, err := rawdb.NewDatabaseWithFreezer(pdb, snaptest.ancient, "", false) + newdb, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: snaptest.ancient}) if err != nil { t.Fatalf("Failed to create persistent freezer database: %v", err) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 434b494490..2401402f32 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -738,7 +738,7 @@ func testFastVsFullChains(t *testing.T, scheme string) { t.Fatalf("failed to insert receipt %d: %v", n, err) } // Freezer style fast import the chain. - ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + ancientDb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) } @@ -824,7 +824,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { // makeDb creates a db instance for testing. makeDb := func() ethdb.Database { - db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + db, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) } @@ -1623,7 +1623,7 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) { competitor, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*state.TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) // Import the shared chain and the original canonical one - db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer db.Close() chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) @@ -1689,7 +1689,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) { _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(height), nil) // Import the chain as a ancient-first node and ensure all pointers are updated - ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) + ancientDb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{Ancient: t.TempDir()}) if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) } @@ -1747,7 +1747,7 @@ func testLowDiffLongChain(t *testing.T, scheme string) { }) // Import the canonical chain - diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer diskdb.Close() chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) @@ -1959,7 +1959,7 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) { b.OffsetTime(-9) // A higher difficulty }) // Import the shared chain and the original canonical one - chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + chaindb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) } @@ -2122,7 +2122,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i } }) // Import the shared chain and the original canonical one - chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + chaindb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) } @@ -2496,7 +2496,7 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) { if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } - db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) + db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient}) if err != nil { t.Fatalf("Failed to create persistent freezer database: %v", err) } @@ -3403,7 +3403,7 @@ func testSetCanonical(t *testing.T, scheme string) { } gen.AddTx(tx) }) - diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer diskdb.Close() chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) @@ -4199,7 +4199,7 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) { gen.SetCoinbase(common.Address{0: byte(0xb), 19: byte(i)}) }) - db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer db.Close() chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) @@ -4315,7 +4315,7 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64, config := DefaultCacheConfigWithScheme(rawdb.PathScheme) config.ChainHistoryMode = history.KeepPostMerge - db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) + db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer db.Close() chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) defer chain.Stop() diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index d98fc9a1eb..862b8cd2fd 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -416,7 +416,7 @@ func checkReceiptsRLP(have, want types.Receipts) error { func TestAncientStorage(t *testing.T) { // Freezer style fast import the chain. frdir := t.TempDir() - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false) + db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: frdir}) if err != nil { t.Fatalf("failed to create database with ancient backend") } @@ -469,7 +469,7 @@ func TestAncientStorage(t *testing.T) { } func TestWriteAncientHeaderChain(t *testing.T) { - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), t.TempDir(), "", false) + db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: t.TempDir()}) if err != nil { t.Fatalf("failed to create database with ancient backend") } @@ -586,7 +586,7 @@ func TestHashesInRange(t *testing.T) { func BenchmarkWriteAncientBlocks(b *testing.B) { // Open freezer database. frdir := b.TempDir() - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false) + db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: frdir}) if err != nil { b.Fatalf("failed to create database with ancient backend") } @@ -890,7 +890,7 @@ func TestHeadersRLPStorage(t *testing.T) { // Have N headers in the freezer frdir := t.TempDir() - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false) + db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: frdir}) if err != nil { t.Fatalf("failed to create database with ancient backend") } diff --git a/core/rawdb/ancienttest/testsuite.go b/core/rawdb/ancienttest/testsuite.go index 70de263c04..e33e768947 100644 --- a/core/rawdb/ancienttest/testsuite.go +++ b/core/rawdb/ancienttest/testsuite.go @@ -77,13 +77,6 @@ func basicRead(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) { } for _, c := range cases { for i := c.start; i < c.limit; i++ { - exist, err := db.HasAncient("a", uint64(i)) - if err != nil { - t.Fatalf("Failed to check presence, %v", err) - } - if exist { - t.Fatalf("Item %d is already truncated", uint64(i)) - } _, err = db.Ancient("a", uint64(i)) if err == nil { t.Fatal("Error is expected for non-existent item") @@ -93,13 +86,6 @@ func basicRead(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) { // Test the items in range should be reachable for i := 10; i < 90; i++ { - exist, err := db.HasAncient("a", uint64(i)) - if err != nil { - t.Fatalf("Failed to check presence, %v", err) - } - if !exist { - t.Fatalf("Item %d is missing", uint64(i)) - } blob, err := db.Ancient("a", uint64(i)) if err != nil { t.Fatalf("Failed to retrieve item, %v", err) @@ -110,13 +96,6 @@ func basicRead(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) { } // Test the items in unknown table shouldn't be reachable - exist, err := db.HasAncient("b", uint64(0)) - if err != nil { - t.Fatalf("Failed to check presence, %v", err) - } - if exist { - t.Fatal("Item in unknown table shouldn't be found") - } _, err = db.Ancient("b", uint64(0)) if err == nil { t.Fatal("Error is expected for unknown table") diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go index cc7a62df32..3a5218c023 100644 --- a/core/rawdb/chain_freezer.go +++ b/core/rawdb/chain_freezer.go @@ -23,6 +23,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb/eradb" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -43,7 +44,10 @@ const ( // feature. The background thread will keep moving ancient chain segments from // key-value database to flat files for saving space on live database. type chainFreezer struct { - ethdb.AncientStore // Ancient store for storing cold chain segment + ancients ethdb.AncientStore // Ancient store for storing cold chain segment + + // Optional Era database used as a backup for the pruned chain. + eradb *eradb.Store quit chan struct{} wg sync.WaitGroup @@ -56,23 +60,27 @@ type chainFreezer struct { // state freezer (e.g. dev mode). // - if non-empty directory is given, initializes the regular file-based // state freezer. -func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFreezer, error) { - var ( - err error - freezer ethdb.AncientStore - ) +func newChainFreezer(datadir string, eraDir string, namespace string, readonly bool) (*chainFreezer, error) { if datadir == "" { - freezer = NewMemoryFreezer(readonly, chainFreezerTableConfigs) - } else { - freezer, err = NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerTableConfigs) + return &chainFreezer{ + ancients: NewMemoryFreezer(readonly, chainFreezerTableConfigs), + quit: make(chan struct{}), + trigger: make(chan chan struct{}), + }, nil + } + freezer, err := NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerTableConfigs) + if err != nil { + return nil, err } + edb, err := eradb.New(resolveChainEraDir(datadir, eraDir)) if err != nil { return nil, err } return &chainFreezer{ - AncientStore: freezer, - quit: make(chan struct{}), - trigger: make(chan chan struct{}), + ancients: freezer, + eradb: edb, + quit: make(chan struct{}), + trigger: make(chan chan struct{}), }, nil } @@ -84,7 +92,11 @@ func (f *chainFreezer) Close() error { close(f.quit) } f.wg.Wait() - return f.AncientStore.Close() + + if f.eradb != nil { + f.eradb.Close() + } + return f.ancients.Close() } // readHeadNumber returns the number of chain head block. 0 is returned if the @@ -334,3 +346,75 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash }) return hashes, err } + +// Ancient retrieves an ancient binary blob from the append-only immutable files. +func (f *chainFreezer) Ancient(kind string, number uint64) ([]byte, error) { + // Lookup the entry in the underlying ancient store, assuming that + // headers and hashes are always available. + if kind == ChainFreezerHeaderTable || kind == ChainFreezerHashTable { + return f.ancients.Ancient(kind, number) + } + tail, err := f.ancients.Tail() + if err != nil { + return nil, err + } + // Lookup the entry in the underlying ancient store if it's not pruned + if number >= tail { + return f.ancients.Ancient(kind, number) + } + // Lookup the entry in the optional era backend + if f.eradb == nil { + return nil, errOutOfBounds + } + switch kind { + case ChainFreezerBodiesTable: + return f.eradb.GetRawBody(number) + case ChainFreezerReceiptTable: + return f.eradb.GetRawReceipts(number) + } + return nil, errUnknownTable +} + +// ReadAncients executes an operation while preventing mutations to the freezer, +// i.e. if fn performs multiple reads, they will be consistent with each other. +func (f *chainFreezer) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { + if store, ok := f.ancients.(*Freezer); ok { + store.writeLock.Lock() + defer store.writeLock.Unlock() + } + return fn(f) +} + +// Methods below are just pass-through to the underlying ancient store. + +func (f *chainFreezer) Ancients() (uint64, error) { + return f.ancients.Ancients() +} + +func (f *chainFreezer) Tail() (uint64, error) { + return f.ancients.Tail() +} + +func (f *chainFreezer) AncientSize(kind string) (uint64, error) { + return f.ancients.AncientSize(kind) +} + +func (f *chainFreezer) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { + return f.ancients.AncientRange(kind, start, count, maxBytes) +} + +func (f *chainFreezer) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (int64, error) { + return f.ancients.ModifyAncients(fn) +} + +func (f *chainFreezer) TruncateHead(items uint64) (uint64, error) { + return f.ancients.TruncateHead(items) +} + +func (f *chainFreezer) TruncateTail(items uint64) (uint64, error) { + return f.ancients.TruncateTail(items) +} + +func (f *chainFreezer) SyncAncient() error { + return f.ancients.SyncAncient() +} diff --git a/core/rawdb/database.go b/core/rawdb/database.go index a03dbafb1f..86f4ac19cb 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -86,11 +86,6 @@ type nofreezedb struct { ethdb.KeyValueStore } -// HasAncient returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) HasAncient(kind string, number uint64) (bool, error) { - return false, errNotSupported -} - // Ancient returns an error as we don't have a backing chain freezer. func (db *nofreezedb) Ancient(kind string, number uint64) ([]byte, error) { return nil, errNotSupported @@ -186,19 +181,49 @@ func resolveChainFreezerDir(ancient string) string { return freezer } -// NewDatabaseWithFreezer creates a high level database on top of a given key- -// value data store with a freezer moving immutable chain segments into cold -// storage. The passed ancient indicates the path of root ancient directory -// where the chain freezer can be opened. +// resolveChainEraDir is a helper function which resolves the absolute path of era database. +func resolveChainEraDir(chainFreezerDir string, era string) string { + switch { + case era == "": + return filepath.Join(chainFreezerDir, "era") + case !filepath.IsAbs(era): + return filepath.Join(chainFreezerDir, era) + default: + return era + } +} + +// NewDatabaseWithFreezer creates a high level database on top of a given key-value store. +// The passed ancient indicates the path of root ancient directory where the chain freezer +// can be opened. +// +// Deprecated: use Open. func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly bool) (ethdb.Database, error) { + return Open(db, OpenOptions{ + Ancient: ancient, + MetricsNamespace: namespace, + ReadOnly: readonly, + }) +} + +// OpenOptions specifies options for opening the database. +type OpenOptions struct { + Ancient string // ancients directory + Era string // era files directory + MetricsNamespace string // prefix added to freezer metric names + ReadOnly bool +} + +// Open creates a high-level database wrapper for the given key-value store. +func Open(db ethdb.KeyValueStore, opts OpenOptions) (ethdb.Database, error) { // Create the idle freezer instance. If the given ancient directory is empty, // in-memory chain freezer is used (e.g. dev mode); otherwise the regular // file-based freezer is created. - chainFreezerDir := ancient + chainFreezerDir := opts.Ancient if chainFreezerDir != "" { chainFreezerDir = resolveChainFreezerDir(chainFreezerDir) } - frdb, err := newChainFreezer(chainFreezerDir, namespace, readonly) + frdb, err := newChainFreezer(chainFreezerDir, opts.Era, opts.MetricsNamespace, opts.ReadOnly) if err != nil { printChainMetadata(db) return nil, err @@ -282,7 +307,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st } } // Freezer is consistent with the key-value database, permit combining the two - if !readonly { + if !opts.ReadOnly { frdb.wg.Add(1) go func() { frdb.freeze(db) @@ -290,7 +315,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st }() } return &freezerdb{ - ancientRoot: ancient, + ancientRoot: opts.Ancient, KeyValueStore: db, chainFreezer: frdb, }, nil diff --git a/core/rawdb/eradb/eradb.go b/core/rawdb/eradb/eradb.go new file mode 100644 index 0000000000..29e658798e --- /dev/null +++ b/core/rawdb/eradb/eradb.go @@ -0,0 +1,345 @@ +// Copyright 2025 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 . + +// Package eradb implements a history backend using era1 files. +package eradb + +import ( + "bytes" + "errors" + "fmt" + "io/fs" + "path/filepath" + "sync" + + "github.com/ethereum/go-ethereum/common/lru" + "github.com/ethereum/go-ethereum/internal/era" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" +) + +const openFileLimit = 64 + +var errClosed = errors.New("era store is closed") + +// Store manages read access to a directory of era1 files. +// The getter methods are thread-safe. +type Store struct { + datadir string + + // The mutex protects all remaining fields. + mu sync.Mutex + cond *sync.Cond + lru lru.BasicLRU[uint64, *fileCacheEntry] + opening map[uint64]*fileCacheEntry + closing bool +} + +type fileCacheEntry struct { + refcount int // reference count. This is protected by Store.mu! + opened chan struct{} // signals opening of file has completed + file *era.Era // the file + err error // error from opening the file +} + +type fileCacheStatus byte + +const ( + storeClosing fileCacheStatus = iota + fileIsNew + fileIsOpening + fileIsCached +) + +// New opens the store directory. +func New(datadir string) (*Store, error) { + db := &Store{ + datadir: datadir, + lru: lru.NewBasicLRU[uint64, *fileCacheEntry](openFileLimit), + opening: make(map[uint64]*fileCacheEntry), + } + db.cond = sync.NewCond(&db.mu) + log.Info("Opened Era store", "datadir", datadir) + return db, nil +} + +// Close closes all open era1 files in the cache. +func (db *Store) Close() { + db.mu.Lock() + defer db.mu.Unlock() + + // Prevent new cache additions. + db.closing = true + + // Deref all active files. Since inactive files have a refcount of one, they will be + // closed right here and now after decrementing. Files which are currently being used + // have a refcount > 1 and will hit zero when their access finishes. + for _, epoch := range db.lru.Keys() { + entry, _ := db.lru.Peek(epoch) + if entry.derefAndClose(epoch) { + db.lru.Remove(epoch) + } + } + + // Wait for all store access to finish. + for db.lru.Len() > 0 || len(db.opening) > 0 { + db.cond.Wait() + } +} + +// GetRawBody returns the raw body for a given block number. +func (db *Store) GetRawBody(number uint64) ([]byte, error) { + epoch := number / uint64(era.MaxEra1Size) + entry := db.getEraByEpoch(epoch) + if entry.err != nil { + if errors.Is(entry.err, fs.ErrNotExist) { + return nil, nil + } + return nil, entry.err + } + defer db.doneWithFile(epoch, entry) + + return entry.file.GetRawBodyByNumber(number) +} + +// GetRawReceipts returns the raw receipts for a given block number. +func (db *Store) GetRawReceipts(number uint64) ([]byte, error) { + epoch := number / uint64(era.MaxEra1Size) + entry := db.getEraByEpoch(epoch) + if entry.err != nil { + if errors.Is(entry.err, fs.ErrNotExist) { + return nil, nil + } + return nil, entry.err + } + defer db.doneWithFile(epoch, entry) + + data, err := entry.file.GetRawReceiptsByNumber(number) + if err != nil { + return nil, err + } + return convertReceipts(data) +} + +// convertReceipts transforms an encoded block receipts list from the format +// used by era1 into the 'storage' format used by the go-ethereum ancients database. +func convertReceipts(input []byte) ([]byte, error) { + var ( + out bytes.Buffer + enc = rlp.NewEncoderBuffer(&out) + ) + blockListIter, err := rlp.NewListIterator(input) + if err != nil { + return nil, fmt.Errorf("invalid block receipts list: %v", err) + } + outerList := enc.List() + for i := 0; blockListIter.Next(); i++ { + kind, content, _, err := rlp.Split(blockListIter.Value()) + if err != nil { + return nil, fmt.Errorf("receipt %d invalid: %v", i, err) + } + var receiptData []byte + switch kind { + case rlp.Byte: + return nil, fmt.Errorf("receipt %d is single byte", i) + case rlp.String: + // Typed receipt - skip type. + receiptData = content[1:] + case rlp.List: + // Legacy receipt + receiptData = blockListIter.Value() + } + // Convert data list. + // Input is [status, gas-used, bloom, logs] + // Output is [status, gas-used, logs], i.e. we need to skip the bloom. + dataIter, err := rlp.NewListIterator(receiptData) + if err != nil { + return nil, fmt.Errorf("receipt %d has invalid data: %v", i, err) + } + innerList := enc.List() + for field := 0; dataIter.Next(); field++ { + if field == 2 { + continue // skip bloom + } + enc.Write(dataIter.Value()) + } + enc.ListEnd(innerList) + if dataIter.Err() != nil { + return nil, fmt.Errorf("receipt %d iterator error: %v", i, dataIter.Err()) + } + } + enc.ListEnd(outerList) + if blockListIter.Err() != nil { + return nil, fmt.Errorf("block receipt list iterator error: %v", blockListIter.Err()) + } + enc.Flush() + return out.Bytes(), nil +} + +// getEraByEpoch opens an era file or gets it from the cache. +// The caller can freely access the returned entry's .file and .err +// db.doneWithFile must be called when it is done reading the file. +func (db *Store) getEraByEpoch(epoch uint64) *fileCacheEntry { + stat, entry := db.getCacheEntry(epoch) + + switch stat { + case storeClosing: + return &fileCacheEntry{err: errClosed} + + case fileIsNew: + // Open the file and put it into the cache. + e, err := db.openEraFile(epoch) + if err != nil { + db.fileFailedToOpen(epoch, entry, err) + } else { + db.fileOpened(epoch, entry, e) + } + close(entry.opened) + + case fileIsOpening: + // Wait for open to finish. + <-entry.opened + + case fileIsCached: + // Nothing to do. + + default: + panic(fmt.Sprintf("invalid file state %d", stat)) + } + return entry +} + +// getCacheEntry gets an open era file from the cache. +func (db *Store) getCacheEntry(epoch uint64) (stat fileCacheStatus, entry *fileCacheEntry) { + db.mu.Lock() + defer db.mu.Unlock() + + if db.closing { + return storeClosing, nil + } + if entry = db.opening[epoch]; entry != nil { + stat = fileIsOpening + } else if entry, _ = db.lru.Get(epoch); entry != nil { + stat = fileIsCached + } else { + // It's a new file, create an entry in the opening table. Note the entry is + // created with an initial refcount of one. We increment the count once more + // before returning, but the count will return to one when the file has been + // accessed. When the store is closed or the file gets evicted from the cache, + // refcount will be decreased by one, thus allowing it to hit zero. + entry = &fileCacheEntry{refcount: 1, opened: make(chan struct{})} + db.opening[epoch] = entry + stat = fileIsNew + } + entry.refcount++ + return stat, entry +} + +// fileOpened is called after an era file has been successfully opened. +func (db *Store) fileOpened(epoch uint64, entry *fileCacheEntry, file *era.Era) { + db.mu.Lock() + defer db.mu.Unlock() + + delete(db.opening, epoch) + db.cond.Signal() // db.opening was modified + + // The database may have been closed while opening the file. When that happens, we + // need to close the file here, since it isn't tracked by the LRU yet. + if db.closing { + entry.err = errClosed + file.Close() + return + } + + // Add it to the LRU. This may evict an existing item, which we have to close. + entry.file = file + evictedEpoch, evictedEntry, _ := db.lru.Add3(epoch, entry) + if evictedEntry != nil { + evictedEntry.derefAndClose(evictedEpoch) + } +} + +// fileFailedToOpen is called when an era file could not be opened. +func (db *Store) fileFailedToOpen(epoch uint64, entry *fileCacheEntry, err error) { + db.mu.Lock() + defer db.mu.Unlock() + + delete(db.opening, epoch) + db.cond.Signal() // db.opening was modified + entry.err = err +} + +func (db *Store) openEraFile(epoch uint64) (*era.Era, error) { + // File name scheme is --. + glob := fmt.Sprintf("*-%05d-*.era1", epoch) + matches, err := filepath.Glob(filepath.Join(db.datadir, glob)) + if err != nil { + return nil, err + } + if len(matches) > 1 { + return nil, fmt.Errorf("multiple era1 files found for epoch %d", epoch) + } + if len(matches) == 0 { + return nil, fs.ErrNotExist + } + filename := matches[0] + + e, err := era.Open(filename) + if err != nil { + return nil, err + } + // Sanity-check start block. + if e.Start()%uint64(era.MaxEra1Size) != 0 { + return nil, fmt.Errorf("pre-merge era1 file has invalid boundary. %d %% %d != 0", e.Start(), era.MaxEra1Size) + } + log.Debug("Opened era1 file", "epoch", epoch) + return e, nil +} + +// doneWithFile signals that the caller has finished using a file. +// This decrements the refcount and ensures the file is closed by the last user. +func (db *Store) doneWithFile(epoch uint64, entry *fileCacheEntry) { + db.mu.Lock() + defer db.mu.Unlock() + + if entry.err != nil { + return + } + if entry.derefAndClose(epoch) { + // Delete closed entry from LRU if it is still present. + if e, _ := db.lru.Peek(epoch); e == entry { + db.lru.Remove(epoch) + db.cond.Signal() // db.lru was modified + } + } +} + +// derefAndClose decrements the reference counter and closes the file +// when it hits zero. +func (entry *fileCacheEntry) derefAndClose(epoch uint64) (closed bool) { + entry.refcount-- + if entry.refcount > 0 { + return false + } + + closeErr := entry.file.Close() + if closeErr == nil { + log.Debug("Closed era1 file", "epoch", epoch) + } else { + log.Warn("Error closing era1 file", "epoch", epoch, "err", closeErr) + } + return true +} diff --git a/core/rawdb/eradb/eradb_test.go b/core/rawdb/eradb/eradb_test.go new file mode 100644 index 0000000000..41047dbbe9 --- /dev/null +++ b/core/rawdb/eradb/eradb_test.go @@ -0,0 +1,103 @@ +// Copyright 2025 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 . + +package eradb + +import ( + "sync" + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestEraDatabase(t *testing.T) { + db, err := New("testdata") + require.NoError(t, err) + defer db.Close() + + r, err := db.GetRawBody(175881) + require.NoError(t, err) + var body *types.Body + err = rlp.DecodeBytes(r, &body) + require.NoError(t, err) + require.NotNil(t, body, "block body not found") + assert.Equal(t, 3, len(body.Transactions)) + + r, err = db.GetRawReceipts(175881) + require.NoError(t, err) + var receipts []*types.ReceiptForStorage + err = rlp.DecodeBytes(r, &receipts) + require.NoError(t, err) + require.NotNil(t, receipts, "receipts not found") + assert.Equal(t, 3, len(receipts), "receipts length mismatch") +} + +func TestEraDatabaseConcurrentOpen(t *testing.T) { + db, err := New("testdata") + require.NoError(t, err) + defer db.Close() + + const N = 25 + var wg sync.WaitGroup + wg.Add(N) + for range N { + go func() { + defer wg.Done() + r, err := db.GetRawBody(1024) + if err != nil { + t.Error("err:", err) + } + if len(r) == 0 { + t.Error("empty body") + } + }() + } + wg.Wait() +} + +func TestEraDatabaseConcurrentOpenClose(t *testing.T) { + db, err := New("testdata") + require.NoError(t, err) + defer db.Close() + + const N = 10 + var wg sync.WaitGroup + wg.Add(N) + for range N { + go func() { + defer wg.Done() + r, err := db.GetRawBody(1024) + if err == errClosed { + return + } + if err != nil { + t.Error("err:", err) + } + if len(r) == 0 { + t.Error("empty body") + } + }() + } + wg.Add(1) + go func() { + defer wg.Done() + db.Close() + }() + wg.Wait() +} diff --git a/core/rawdb/eradb/testdata/sepolia-00000-643a00f7.era1 b/core/rawdb/eradb/testdata/sepolia-00000-643a00f7.era1 new file mode 100644 index 0000000000000000000000000000000000000000..a601a40c23b4f0030d15a4a19684aea0ddb61864 GIT binary patch literal 3267454 zcmcHC1yGdH{y6-lJEWysq*IU%k?!u2?vlo(LqI?Qm2g42Lr_9MLXbuTr9oN{0YO?` z?uEVkpZo5;_cyz+cdzn*rc606?q4 zo(Mw5KSZPg0sIjF(IBcmmDQOp6aSKkTHCt5FXSTxvJ}r^y$H9mrB5ZlJe7L}P?QF2 z$$(7j7ToinzZ-jEqme9tce2sg!h4%!x0d2-dR=tT>)mG{-BlV=iawqEvoP7^ngdD&UJcp{*4d)Zr^|5eVz+SJAZ3 zK}>ml_%1)(g-T2K7^vLM$1>jfY+|$PNc7KY2)z(@9{=Al<|5L+E%!Y+XX7)r4A%Xf z&w+pGL_wdZRQnC47Epuuv4qP`P^8n8)ZR=!uef^%ETRVC)KC2%BK{vqFzEhWVoTy5 z6bN7nPjg`)s2?d)2Yu}p!z3QsV@;Ha7$Q|+*G*x50_9X!t#;!@_UNvo3XeCs;lObI zTW+oJLm>Yb1^@s$#AX0(EEvMxIc36@Ip6=(==e3yzP=SdyA z*^7LVjfhx18!8%~s57Qk#WW>39rRy9oO}=G$O$ckAL6{p_%9#m5F;=Ad%+Mf^*(1M z_?mlv_I(%akhBZ4v*-RWOr~?uHaEPw^CyZ9MhHe@OT!<+DDEJl|JyI6-99 z+={5#E9^!CBSc)IfZ)gO3_pB1goMHXKocKLxvHT6KV8}fG{`YHu03t&mQh}h* zEy|mngh=i9xS7(85?G7v^+9aunZGfrTcZQaWNMTyA%<>+({DLpzzfj|z=Q$fyR4xy z7((#Q@hf{DYFB? zRSR43kF+kErp2Rh>SWVscp-oY*f2owJ&ySfhG=NUwzU(bSYcVeZ};+bEE|*3?s%Ic z9Zw?;(hLu-5(|tOp|u-I<5SACBO@fHi8qL#@X1U=aMRa}mkR5FKS^t0D^axvM`2ECd?;>D?*rHlyMtO8E`|$C4(rbW_M1w%QIPW89P3XE<_4^<8Rk9AV&Z2+ez13YG zew5aiZd+U;&wzOWq3@FuPHKm50WU-=5%PJFa)<&VUxT0INc%obk@k?s$4PA{Z3l30fb_O2t+g1?{P3fEYWTbi>eoA z)cz5**t7N!75czvWQX6fWUjwFACR@OdJPb*7!ZhbAgCnzMO$No-j>XF$C=x~XSe;9 z#dG~5bFC}2d`f8P)N3vw>_WnCtd~B97XpAr^gkd_|9wJt007Y4DM>nqc=?YBoyPkP zk%Y2-O&o4O{D*tRVLqX@dq^dZ3l_I+I5P~xV9f}Hdf|Y-8a`itQhIsU#HLQASnsBMAd$jPyMgo=;5l{Ore7uRP) zdnl~e3jEpsSG4~d2lVMPq9hgsA`=Mud1s(E%)8wiZR}(CSL|lf8RR1|vovARvjV0Y z7M~fME+MuR!*SlZQNRl!iA4qjMBki!Ef|6*`c&$mi zCt!$9+Lg1V;GMh&#w#ZC4k8|C>WpkE&Wn>D7E$DHBg@Ue2%)T}<%iVXcWU2Gx3#Ej zvC=)*D?9#RnCNaI^9!8k)R@-*(TW3scm)J;TJTHX2+}S3mIDxVQurR?GmNT`M>BQo2;iTqx~fetzWF0>jSw0*rw2+0&0OLOdj?3H@j}ZMNN? z@hR$i*HUd`f9NsxzjNxdUCHH;wdrxC4Ja4YXv0}2({#B8 z2p~QLA_oXU2MyZ{=He1f%YIU@LpGexdV>+So>)S^b!!fXXXXjv1%z(YlW;VQCrR)^ zNRrdT0P)}#aVHp}qS6~?v{7Bo13}hQ(=UV^8X>M>zQWNDcAfnO>S-3cI|=UVL|w5QJ**a zN~F{J)n^1UfB*uK3j`^zJVh`JHK37>qJ;GFIM%5xZ~L+gz2Yn z6f2DlxFP77VSorT5_4G@xq5Qsb=$Z#g9T?(^?8ckRF z<9J4$eZ+9V(YTSlKy9I$P!bp0=mmtHlv+4)-AV<#5R%L+FhC4)-R=WJd{Y`KvP1>d z&PFlFJboAUBSN+Fqa)AaU6Fx#jCwEEH!wn2>4g}YM7%;oP`WjLH_*o1uYd{*Z`jB% z@GV`m>WStxEU_X3i69X9K#+b>jsTtSUE|DOeIls1BM%+WK(X&Yy??!%h9v!_?tHlH zBan*1k!dj-;Du;qWrYDEx~2~c4AC-pgg-U;y_3NRwZ=>hG10&Axaj@}yKteC*Q_SW z=Q0=}Ui(y4{LO!)QsOh`7$!fcR{4y+r-3LgZQs22Vemr{-D}8*R$>T50T8sckuI9> ztLi5&8s86A<-wme@5>A4IO|DGJ??+Y!=cE%Y?>S;!jUpCtl)(Ja$GpVuN@b7c}WCKVLlr3V;LxQ3wRN53ACJ!cbZC>j)$HTQtUeuK_}m6arBM1hIQ; za`H?XY3EeMFH8A<(>XR5$}wT;C4Idlq;7_Q`}?ww*cuE+Z1>@T7oznp_y2%^w!|tg zY(pz^S&yTS{Bp4x#jtS=-L!4`o zBRjm054v&EW2O0R(`D%>T4OhE4}Sh{YkL1}i4_G%28nht5LA%BLOX!dgU=yls%ygC zsrqenI^)koaz*j@XmZvQag)nvw@rs5I-)DV8*NF6%Pn31A?DEcV@yzc+ysB^QK#C? zOO#|o3Vh3}ria@_554N0>urv?Ro;YVg)f#V!x-%ktIy(d?C<1;^#|c}XnMHps(KGZ z@FeYE#6@SU=@X4#!`Hs`CIq4c2qIRsJ)ZD0{!v@|&I#wUz@xpAy+qpKDHkFsRy8x* z&-E7&x+gl}h*SmA@InA&`TqmKMKyE?bc41uFoXtrT;+~w6#|M%lj2TG;kNdHdPJt< zhu_&roCf&MTVP#cEq+<}mDXM)SAFb$AFk_nyKn5~HUU*=$2vNBQ)kz6vH}lE8McqRAZk)f-dUPRSc`nGpjb;Rxe9hHyhD-GKq( zTYDS}7(z2LR{6lcGuyZs@qj{vruI#Q=!eDoPG;FPmbRt*zgA()2)v%bp11-_vv(~a zPIPaVDkN_JqXdteMzCu4Sf0OqT67H%k`xe#G9V~oqSVdi8TuTKae};P`#obFUWd*~t=Bb>u2BdW#dYD@FcuTEc`o|O_1|q-+fgpy5LEXRl zn$q8?>T&6Q-s3}poiqU#f@~@##{7AxeJ{G1|AAaINe3 zl&0-1O0xS3sKy5#@J)qnjRt5*%&`yA`UbdHTq|!R$MksLg$Yv zh=+6FhOid@9}u+vz72o?0f1p=Uw?-5kA2-IpwNcy{a?3$B6}&cdhszNj5gNO64pB_ z`|R(iQz@-YK`=t#c63f&V=q+t5KbVb9I_))+dBU7+m7vBnsH!qq zS`ph6d2OaeGaUra%ML2d1zegZ4B(|xzrT$A^JrULcli@>+p@YyD z9;XRslE}}L1_u?xBucQuK6aKVT{^vYs!Ari;z+(WuujM0wo`1#et^K42g-Lmb|npGP#!V5{}mYRRT; zmtE`88gzD~D++x7qLrk+%a*Rgz3(y~5^sf>J%szrPi(#_3=Sfyv2tLC(VOpVu)U7< zx2l)DI~|SIe~qy|*dV=$a>Vj{!OM>428{VIk~ujXhOI>Jdi#qZQCyM2X?r?(JnLJ6 z8ai?Q*5?Xm*We&~3*t}@1c@DIH;7RLV^);EOrwt*=C`ymczUw^%g(|@I&%Am_VI;- zxpPjKR+K!v`7l_a4ueBKqjM+NLAIiC`KASr!smYc-0~f*5p~*iva&7&N$Sd5cZ4aB zV4cTd9KP1i(6O%lc;Ed~kKJR&XmnynJKeLndx`u9m|sfYU4ug;3&f!T2(sP(#hpI# zH-3azwOv|XLN&5A1A*8{S1>r8FK^-(59q={FLg3Zfy4}62c3FN7#y_1usFdEk@v7o z3ONl>gL24U*%)v+#2U<`O66?sJK1KdzSu^|hA|)RPZ&>lPI=YWH!^ti3+V3rRex$E z>y&0VU=Q#vP<$+R4GvwmAr6f|P_!h50ezf&FB?zdv*JMy#pk)d?a6dsm&dnM`UF+9 zUG@(Kxk_OYzn{VDK-sPhg98ul4mH>T8DGa{*A|h;gM}OAj;r2oc;ZU@R}~K)q72%J z;e1SS7#*4fEAj8*_{!<;IXy&jZd&q9DLnSBQx-!FO8B~VXQk`v9Wc>ZAr4JI5KbVe z-~>yNRS4^yNY-lNAOakzNKG?L)^Vm%2`@C<%g1v1w+_Pu_vqnuVC>h0!GSxkW)bYr z;b)HyNRynqXYs_rrGIWSt-^+8{-E;{2O`4QP9@$=7#)V{usv|c4l<~zjB?SFKXvg~ z()+!5?U3r&f!+Q-y20-n92D3f4)1{=Z}pxZiYY&RtV&h6`Qu3pU&J@uQ#5wIn|Tla zR?OrN;6=NnOTHV%{U;b+2j{Q)FgVmQZOnijRHw&sObZc&uJ971EWKB4YkusM8vj4*~+>=KupzCk~3zX?P4W>gY+afm$v*G9Aeoa4$bG+ z2GsuG5;`cO75mcFc-(Qmzx&8_b@&a=&@QvGY6b3Hj7x{H#W2>daPJ%2pErcT;gHh4 z2<$M%Wa7qNW_m*$$t>RdJN{21!389onU%4Okdo=8a8Gg=9e$*;2UpwK<+@>D{0i<#L^&Wbi)rQm`X{Sl6S=aB~R%Wxi|6BSwsdT>tkEiN8*!t^-Roj1G5X+Pc{0znr#l z%~LDomb19|>jjgo-$s^rFrk% zJ1K|S!Vp22Z_vr~mqSEhbjTrEUTy>hbvHa>4pK5V^roH49AP)9;9g%U z!nK0ILDe@`51bFCC~7eSnsFf^=;Nt_xI(99ILz_4M7G}`N$>tze3FL@qeFwyXCF^N z!aagm{9Q!Dx4(;O~z4jn*{+>4(Xx1Tm|WK6Q<-u4JWR+m`$8wemtT(0~}5Su;0ci~{5LKsFU zECp}76wPc4gF|yOWjWa4g{=zmQ(HZKmSHqMzR^>c{4KGDocpb1<;s=X>Ne@Ht}peM zOid@m%?55#VmQb=6Pe{&e20JB!(+hJt?ye~pImHNx3P3|pGBIC`u92GnSee;_z=EH~%qsEjJ?#CRR`wub2Els+`C%&<1?N+E6 zBzX-iLoz?a;Uf_AzCb>}PvfNz+x-t6A)FBph25oKaQLtoqYZZWx+lZu7D$h_^P$K=0QhX@cW3Tv#`-odGTfF??~tl0 z7#+0vLxnud9y2`1bi2V8(zkg?#t=R}m6x%=rrc@r%9{8Z97Y5n4qZUdJl5Ct)HgX5 zEI%bv2=XYT#Wy9~D#md78tQ&7W9A_gUbahA@58X?qu_NAS9XTM!CA*c80--COT4unLiXS6(}x3lrIt)nf^i2jr-Z5Bj+_Z=mzIs{8py{P0s9`D_g>vJwa6i&+c+F~ zkSfA!U;WxRsi^jC|1~_1!$}o_IP{!v=v&wMH8f#9Oub9+bQfK9CdGAd>ZKo_W>o&2 zNK`;v*M);F*FhM1Hr&^0hQ#(cotHce*ws=RnJy8lDmm@&Qdefm*O(hBFev`iU$Lfy%0$cL|YAr8Gj zkmYMvO_Cm6rbr}L_L>4JrKeoInj-uGv;I$cY0Z1y1Y9`ijLd|g#qGhH4@9BfFgS=! z&v=3z+@ilXgsHRc#YDN-TC6g;{6qz*`u~)N2BSl?ZgF^@3wp=mM1QB} zYut((xAvcJ#&%}OhW<$OmF!!)dIwxGVTeQDc|MpFa@Q4}X|aowjHXpYJ!(y(I*i0d@cx^JRPe(l% zD5PMBb3;}m(C4cFj1IeWY`@3|*xAMo6#Go~k38Fd`w^q3$$eW(d}8tdqlx<(91PBn zm0VmQ?P=bBK7UYE+R6Wf#?}4kmaTCYKIZ+u8z7DPrTao%?j;i!; zOA%RqFgVaZR>A~3%tfS+cex+_lr~B>pnQ;EiEJI!f?PJrllb@sZAur%1dI-XLi#vq zmN&kq@)!=^q(HhaAK2ISYx7R0VqU?#1lr#E*$h#h{KSb z3E*`&Y7BzGA*+~I670Y)6Uyp%`NxJ z|A>u@Kgj6WOM|(Y`COBi{rmXs-{qHgE*V+^!Vvf2ZkKNS2!p{v>6_8Np2v}^4l)!oVQKLf1>5Hw92T|upO?DkA=kc>o5;S2Y_S7EH&*N`2E%RwXHrO`PLX3Ndjw_ZTO{7){b{_& z2c6Q+FvREF@aDtTVFU~guhE15^&Du10NH(yTgy~V4w0VRXaFbBlF<-RB5x_$rTh~U zO(m@JX+LA`4Zrr&4UQh|;i*SDr$VtGeyy|;$&-WSQ(@H}ez5qdo zoqN={z7~;#qlr3qO=7lP3D)c#Jhda0Q|xPE7;lGNwo6i(VTiJ<@H*gQ{_8y|P(6?U z(9XvVZ|r{s_YXr;oAq$h2#1~uJweqBX7I*defNv=SaTo=H@X%iULbjoivXgo=p_K3W zd%|3W?P*YQt*(V>fsf;`Ctc`Ql0fF7wD&FFw>lwV@2i~APx zRP^bm*D=@Nkb4i}Fm`_aL3z&UU7-)ty0C8}6@ncZHD8Qo(p{TjQ>(4HU4c)t7x|#O zfDnez1oyfI30oXE0R`52DITNi;MVGkuNivI{Qva zQR7Wubl7~UkKpG4h}p(LRBD{Th*c#ueMq34$`N!Egy_CHV0R4;%d!xMujiM`SS25P zU9bw!FiowF0i+Ynp%!&<;YH1S(BLDQT~GwyvLTKbh7bYwy2gn}0@V0}E1^3OMq0*z z9kgAlwQ;6(g$5$(OBG-CB;e(v{CS+XU&~or+pZF{@fJo0yk?O>zRwUe&u#T0wsHJb-3uNLQ%! z5&EbsAuxXH7g-MmuNsUFJ1beF3>v80QwV6b)I)0}kF(+q>i3>A>tksw6e0V^UW0>! z9K>N92-0mICe(kaQ{K=q`P;^qX!9L48@#Ys>W!_7NrHn8HR=C%_6HJq# z#vfb>-9es~gA43HK<@o1X=<$N-~-W%-NL=7`ADf#I;XW4G~LQ1GLpUjhj+k1eLop* z0l=bw>tJ40k8+fS!FzX|r@-7Pkg+kX9KkcApK|9K97^RO4ii9-qCJ|X?A$1Q`88m*b`4*)RlTxNnmdc6$a6In)vfK=beS3EV&ckjDEk z{r%^C0>>b|5&}TsVT0yGV4(n+XbW;X@z!VL1<4RET#Aj5&J}eS^C3m9=+%*xaY^Po zR7rGdzLB$nhs$#>@7}a?`GW342jID42eB~38=DFche;r4<(5EN$Vpbb%Yc-B|KBE5 z*N>hvUm9F5?bC2FGElMOQ_)oS3+kf z#rbg$%m8}zg>8{TK%-b_IlS=8;+VqjP^7!u^v+S~7n_IKMVK%$B+W!Wa4-3qh@U#$ zv2FK2DBLev#VSZXg=FRPe9|8IRljTCAKCCm8Nx7gzQ~uN8u;sk)HR8j@Ni26&4Aej zt#tkYQ{H#6KyDJz5Uxvxah1^LEATP|*Jpqu4z+~Nkn_Ap0L&0lX%Q$NKa%eI+iO#b zcJT-yZAx)KyG6Wlo~L97JMIsR3@&X0FTWzl)&8`TN(hz^i*~^ncvs$F8a}j{9Vjaw zb=7yA{Da|-3WQ-62>SNbJwL5*{u}xu-P~r$Ps_34e23C{2I6ed20x=bT52yFrMtUj%EIF7#wucq-LadL2EERuZ^&^2!2PB=!a0pNkiNira3-PY=BMMu|{J6~ZugewjCm55shc z4C*a@c>=t&YTR)Z291scN9>@n$T3tG4EzfQGuf(8Z@5=lOJ_mgh(j%*GuTCy-Uc%q zbte7&qAWQYqA4X?R7P&!sWhS6+J`n(IwC5^&4K~z46g3o5JK)#nHXy1^{rmZOmga9 zt20(!P7H5`d}SUuc3t&~_jxuD`l~@0=Fcy;$Nl(L29NT!T5=Uvh)e1RS0v$uk`~25 z6AGpe1d7h%7Yuqa(xEnRKLBF>odY%e;7aHWN5g(2V1|c{^ctrlYAFWlMagGh5s>8s ziW2wo0nJJz9|=<;s~KU;2F5w(gY*3m@?L+0GaTL2o-NGG#4DGY6aB2+wK1B`zJ|Vm zut^=l@Er)spDa-4w5w)7=zgdDNtS0gBZaYo_-l~m1F{=xPt$?z7YqhbPeKjgzK85P zY92V^P)q0xTC|S&U8}`wX+MwBRS0ch1K?y$^0DI#+oR`E_U7bq(fk2Kqg_w zll(;z|8SJ%0Of_j_t4q*ImXYd6V)BJ+_|w+{x5Iz{*Uh~gYtr`e`Ld74G6;m5Y(>7 zk~-2?skS6hXnk8qTxvpSx+UPQuvDf(i(FqC&*i>Wop%pHRpCDNFh^bhHT>X8=nR4G z7JXm_8ZvJAczWB_em;aOp`80a>xK3f$Tttu@a0eEt4mCqVPyEtME;gTK#~ymFs=N= z!>zf`FLd8>}ga|pXOxk0_Nj3$!lQf(1tK9pIpu3@A^EUyb;SOtO@^B3sS z#{@f6NadY=b8y+0jGSgVSI4Fk8c8M2BK;P;$Oc`pyP+(i@G`s!tpZ0JY6+cT*(vWQ zm?3q+qK*+2v&v3O5L-hD(8%g>h)+7QVKh+t9Z|7BKMO{NT~Ls&FB)3ir`hr2+kdS? z?x7?8-VmE-9$$|e=pf(5zJ_dw)q^ms0YQUWYSc*T8Ha6D$VJVY7(pV*JxO%fD*W3% zk#x`RzE`|p(D$_nWe|XuLHv0Q)bN8Vp))ju^W6Y5q@*sf=t%Ke{I#yGb|?NSFGf^8 zRz`^HYv<-5=p9Z7>%2j}L`CWCo>f6t*|1t{H{Tg^d(Hd0K)+O6j0AzY1L>>Ypm9E6 zCGOLQF#G_5OuiY&#FpKfe?qsGZmdD^)@EYL`q99ES~N__S13Y9AbRmP?EU@Kis-Kr%{- zUcZYf1|!2OBPP=<f80tx+ye0g=LDbfg#xl!tfIaI^YiF zAxLd)ET2?J-o9ssM53V_CU_K-C(Xop#7GslaoI(WM1>ON!OL*8)d)5G;7aHWpL=B4 z!3<|g&%Yx%1-dOc^ar5ail45UwOA3XYzHn<4Z2{YER@2?uucA};PK3p6~M;#mcSDx z$FcC)LN#p{gQ|s=iqu16hHGH>Vhmx}1cJ~$q)eJpl0+rmxXll;d9sjOh-0kv<0i?d zPdv3pV@uTqgOR&yD8UVQ83xdr!4ZdALT8|kJIeqw4E}oY@nM~ngR4DfRb0o9yW11% zvIdP_j&0G2WYsm}crY>~oZWcHAC-|GWE^Ynk~AB-_;+FUB*hSQGEqF`!!qYJ%%Vw2 zOdt%ufFOHoee)w$VbN~ZZj6_*j4mkFp7`GM4!wPPq7p88SVx!HK&lgp2X_~}NZkrG z{NPIH4EOfcyub|GZN=^L<8Lri$5K?+J7#Z+AY+y;&>B)=04Hh^@%EEoWXQvp{wyQf z)ntK2n;NkDc9)#jZ%I4In zic@u0rqL(bL3s~;$s`dA z{wcp)=5sWyy!G5-CZd_AYsf#X1?Wg&WS|`SHc_P@Jk1MGO?HOd zYq}?C$G5M6;iVabVH*f~O+Q8TgjI5xqTleN>y4r`&fPil?_*gvaK8QWKOBGTc)_4g z?+}Vj2`|H#N(a>NgDaskWD+Iwff-Q3x41FX$h-<{sdww_#R4APOJ1f}+42zzC)l)R zvxN1%_cgzlFc>RIb(#p(D-}gVFk?!4D??Bst0ODddWQ-sO0R)o${fP50|d$3Um{_- z-F`UW*D9#6ZN{~xgXyX0{5Jlf_~YOk#le>wS@m4FLNQ;!%TR6o5gc)-C3J?LvNEb* z2Af*_E-QWue`jg(Um zXVGL9mJo(rAn1whaqNgz`%_L=``j=}A>;&od%6U~ZB#Euk~`IOl!?GZ>(Dau(iClwn99D=b|9gQSY|L7~LjrWbRBqfXQe)Bz(yS6vBN zoC;cs$6ssC;CH-HKIt-fB;S#4b1)BL-ws*TxQ1-VwSqA00YTlgTP^KqSep!LPle`} zx9w9%#sC_3m{)I?S0g$fCU;(BgF%OIC>jO445Q_JP{R+dgwD_)7G(=&sC}D8<`w>{ zB=YXf@kl&`e6@n=1JzjyN58N$jlglYe~%6xhTucZ3kIFE=1>%Oco~-GhMoyn}X!u_XiUj@sxiqo;o%obB zIMP2d=@wT);FD!6GiMjftG+_xyl=SaYy)990D^iR1+C_=-(h!n>htr3A4U%ESen7% zP3H0~LY+h}ZQ1_IY_R?rirfw_gVxb!aKxdO&>7sY_kF<(DW}hkbGoY?yFLx<>7!`G za%JK^DakwdbwdC@riD@!1x5zF&@`I}ee)=)7$x9Ik6Rq` zXcTJr!IjV%j$_1y!3=qf8bY&&E_>DCpOBkglC4eU7uC-EUC_wmL=>}1#212*ArJR^ zad<7ez|y+MS@nI_9@<%xT!s&Li&^;F{IQMR`q#kl+YZ8T1O!d+H|y)59U}?^=wQU? z3}~BFD>AvWuuDGNDa`l~ktch}U^ozpln*b%AC9l!h(j&^1H-3!O)vxcx1yN0b%d5u z;dU>9IlFQ3;j@I=6={--7z4eyKaSgBWOzCAX&p5UXVhF($DV8R^r6*q=WbQcA%EdW z8rB%OLDCO%1VW4(PyqVvM={X&Fv6~W>o-q!<)4M zW?)6D>$pj(_=)3JTY`f4zH*ILkQ7!0vL$wMmb1fSpW84pi1qNX#3_&pd88O~QL38= zY^L09aPFu6q;K;{j$n7b;2Id393c#+KoE*31AoBeU%pknCpzQz{raD^rc^o4IQ>Q~X z9oc`i@ucrF4zlTCb-uY^FyssmMVN<|A*W^@YWTsG&>64`HWk4Pl%mI#MSLAw<21Gs zk#FRw>*A%+4j%t%dkRvbmZzd+g^^+4Hd&26f9{ymq9@2CMXsM@tvQOik*|_QIJ&m{ zCe}4X{ z$FtvNZtHzR+LJlF(ZT69)SBk~$m#(S&gJX8=nT!~CE;KO z-skFrqok?f>1sa$ob2C|zNKyeetCE}fMfe=FHVDd0mf`_q*Lc>Sh!2OFh(-ntE`ob z@QkEZg2Q#7Fy_PTaNtkbt7o9Za)U4+o?jSEzLsJ3c|D5wacsBRd#z_@xS74XFSHA^ zg>j7;3wY))8YP|1u}}mVcpIf7)KzfAp_b4Y__T}v#qh?V->L5A;uao5Z5%V#n$6T- zRAcG(t;1JCd!^1B-kdNp2!7{@-FSlkzC`O}t#93?h}NutIR%fJ9NJq%%rI4p5Dkc3o(rJa z(9oJ{Wk!?icw0esxuj$;jubKuuR@veCe-MIE1@eaeCtOBD{$UhU{i~V>l_-?+)3h!vT9Hdv>doUdNmS=2^CPpbR_ZQt!JzIe z1n#rx9e!KjfI}^zD^M6XJO?X`(NG^m`-c6(H08}|LAIu@MjMvfZ`)EO?~(Z^!q2S& zV=j0aa#r7+A$*L?_@yqlPREysVn4Idm^toY#Mg#0nvtAqP%!j{D4?AmZU|E5tdk8^ z6bzpi_u%Ssri+e>bytzP~wgWZ#;7aHUq(&qwU5T9C{zb2Th|qWIW0!&|`E3=l=WXh%xnR9M##Udxvf1M-b)|KP;0{(kdY>r% z`*Eh1iiSbnXtOuDulh9t|Hy^RhY$sHAV`Geai;T_ro>@sXL(R%8}NDVQ2?TFnh0%4 zLTeHdw*;#5k4tRP_9yVBO#i8W*I~(p`Z$ zK2Yr)F07Yk;+U|$?5Da)gQ7Qp0jI1DDJ&jfrWS0;J9GN`_Dt|kzSR7U@vFYn>K_Vo zJ`e?r^GiSlH6D9U5c@v%ubXCHm@Rqbh24ZkJ>oS+pvEd$vw?TnJ6nu}gutti{`n8o z=z}Yf0F?heM#4n^v=PnQpZs%-bO;g&_+iT!`(n#%fO-B# zZ|?lQ$=~!szkBg(M`%nZk+<-V+N&OX6x5oNO=l-Dzf6UQO1Nij&07cHa6>KsgTdoJ z$6$j!bRCeGL%d2mgYE)#!_CqYww>R#M9z^z%oIxo{&)3Z?G=zVz7Mzv{ob=9`w>ag zo#gxJEV==g=h4{9Tk|yACH7ZuVB-fdz&d{dU1t_Tv2L=5GgKZhJZHE%8{mnP7e=0w z<>zzv$E4Wh!ybc&=vMIN0VCcq)YyY7p&J}05%7Zz2)(!I^Udn~0>vn(x?Z-V1+VNi z)!5xt)o-w64qDvBg3*Ayllvev#(kr;$-%G3Rfzt}o92NdyuI{-LM_aI)UUi(Z&2h9 zF~B~56Q8AZ{P&sK&ynRgz``PI59d3&23|y>&xRfPn(ZG1$Xw<@!3x~h9QJdZg2N59 zgl^!m>xvFGpbxG};=IEn^YQ)08n6At+2iy_(sZw#%oSea{ur`$hxN)BO7*W4N!&(0 z6E~2bY(?LWJZrRTe*dC==2VnRs8vD1`|1rg0w4xBK#*Fv3n^e!5%=^r#h1+mi~Je# zq(}ji7kul->3 zGxEv}Xt)9)2Ds_-*YAjoPa8So|a z-9m(1?7-}oJMvqWlBK;c%s^G064i z2G6{~QvueRt2d|(h8WX5wy8-N7<^gIa2oaZ^#)39yBQ`AiY&UInE{Y`4gnS+3m=?-Ha z&@g-3N-aCvM*lhcWh(zE&D$iQ?$68@PV3*qD7N*VulNl5`Ph`^;1R^&1`w1IVQTqR z_?cStC4lDHV?MWXKAz|AwY-%!TBDTo*Usg2;m6tNFw|+>-P~VS{*ir z-MihBEwwX8+=7`};J%n%dL07>1<$^3V_*gQHtUm6r4-Dv7Y%(?nqo*^3bt(3 zNbi$A{NSP4wg)=HsPJ(tmRIx;!;@r1cNdvzY3{96otw@G{pbqgQaY{i>NTw1(LM?Z zfhZ83kBx}Sv1;Eh(25uzVPndkvdMM-wHhq!zE9cy?tBkG*X8y|9WyDoANha4!iGVi zs-lnztZ)wvV^2BA{ZZow&NkGCPWd1$g_k&T^EN$dyl(P(+Ho){5HJw^R^TL^A{4`A z?%ud%@yB{lTqA2FV;}#nS!ezHRbTM=k6dUE356&S0YRF+vO6F93Fz@xCx7_!vT1Q@ zxxRS#!83Hrwm|A8;7!m)E|~0&(!tvzg|nY8K>U{v^mQZ4Lc?XS0#B&HnV5qM{!?>| zMxMJ=3+yA>NC}n-r*Agij>l$IE5NA0=x6<53GbOS;#9Wdy_$h&C$S&A2o675ng%8v z9{z~C>fK=H3Up{8VGspkAgEy8Xx%$|;)&{@L?!8mgz<&#N1032R!s)D*~ZF$*7 z?(RlVK|&;EK#`O#si8|6LFo{YRvJ_!lok-A!-xBZaejYX&wU-o9`W!M%!lu}_TFo) z^IY^cs;r4bM*EDUXR|t~fzY2rHUmtwg zi%YTUp+k=@oK$`&UaNLAIkm1WeQz#`i3I4?^U*XlOto7{8sin}D-a7k*76q8<#I5J9T#P@1E_$bn0~Wf;pP&nzxk8fZIuNh#?uX{ zH3ThZRpq=DHOFDspkN9PgDH@MAT9e?EjrX0R2jbSZ>mJ`Q08t(Hj{|ds5uPe*DDMY zcw8zNzdVAw8Aj$YkGRZ)|LxHK@W*R!5gAXM}w_`%#yc%C3*Yan|oE zb{&hAmtOX+`4J5QR5*LQ%rmNMSIJhA>-B9y4WTv9yB&83IY?w>&g;=g3g0zkp%NSo zQ=kDsB2|s1r~GDH$&dRE5^7vq(1U4tJ*abSBaG?(|bTQ%l=dz0a7P}l{(fGN;|AXZa?sDY@ijs5ugb6q3ZR%~Bi<9-NS zVIt!q%Nc9Dbu|y#SmziMUInW@CIAZfGOJxsh2`h$8e2CUB#dJ|+?;>b!ckVM8s1gc zvvekFmBmfvb^uVpMPd*F z$G{ZmK#+CT$4WuA(WG>4H{BGfC-}dgN`T6KG^#<8m=u?e&XO;)pl^YW0k1;JCJO)s zkc>nHRAG$xU`3%wfK5}gz{I-YwrI)(mW`7T1@eOvNX2o*Hqb11L^pm=bSk$kuXaFA zazyUR<|CGnbN|I!E~~m`*q4R&@3X-01RM)fxDA55lE1g>P5qKz!;(}+wA(TXb+Wv7 zP4JM(-S@!5+YF$nk@)FmuzrfH2 zj)N)CgCI*q(%DOQ_N)qQ{YDbkA3i~zY>u^{Z1jE7pV}QDkB@uxzTks>173wsLYx2; zaB7Qkpb9uQV$z+@R*G!N3X5=LG6Po(EwQ%sCAFCom{zI$HP`?ubl}~v;?ODTBjow; zFiBcVV|UdfsJkfA`{$t;=P%-4+y6cbjL6`4m;wU`^89^k#~2m4|K#0%>;5ya#h?E9 z?Wy=aj0y?1d>@^&D+Nnq3b+-<%(ww4SgUgGKotaZHw7Qs`DY}mpVB;jpIfr0>)T(< zl*{s>Kz>uqS`g?Rs{MvfkqY}CHbg())Sbt5P4H3=^g%<2WGS&{u|F6z{nta$FV+P{ zMQ{R4f$^e~$CoFeZXiroyespgEj zqqQxhTiop&!goI9a#batL-K1-7zQW7 z6qrDef?Q#ipoI-;~VMl)uZUMd(;yTh&EH7E!`A)NWM z6f_H;l>eN479e9I&hRR>qr<_?au9ly3(k!e@v*+G4sw$NxGt;=95FLi=lsF(`#OGm zV?LBLcfVv4 zX7n1oWa--TcqhyBBnF_uaMhd#exGD^cmvvFQ)`Qw(rWFnacy%YF+<{Z_Xv%DeZ~2I z6b!*BFa;J6#MV7@RZ0$PQoUl56A9ksHa*FT%iaV zZ%gvSe-LktkNeVRs{E=VHHW~h;3p*kKtWP6#s#Y2Vg6~HZ++@rf|vHIiu<2jH0^Qd zgGQUHW#jy0Q!~_h0A`^vwY&V8?+fae?aH}ZD~c!CwF52hJbLMgKNgidjrj79Pip^f zMfwI#gDJ3qAU03u&DpS=1Za;Um`ryjlyCmR|DiR5?H3aF`tz%v{;TPpM&46!D;PW8 z1)zWuz;qv~5cxX0C}K*zv<0K#&&&Czotl)oW@ zakkfUZj`R&LgegkRvn#{DXwmg7&aNet>FJc8i2x+QkTEaNVO-sNJ{CZSj=Gjd4J+x z?+F(2mFyrgf^$lgyYqr)^Z>JvVI!0x?IEsdM_9%i8+FE+UWYY~8SgA|ETeK}@8*c` z@1K#F9Kq=@1&)g|^KVwlGF0PKZfF)z-Zm}`M)TrNZxFS$uBW;*4;)ORnWM*EbZrUrtLg>%j3k;`hPB1> zQnRU){x~bBFJD9{wL|>e)4T-h>q&%l1@$#3lz}r~3Y;Lw7VSJjt?nQ$b>fWKV#Cwe z5}WdZMcLjPWTEl9vk9_SyZ=Vjh;V1&#aDR%3Yy%qb5MmjunR;UIZT}1it@Kwu5o3c zAqk|*MvIZIaWVDzA)+L}EChp6gIc)JoEJ;xl(1rC9zNK+^+h$=j8r4{HwYwgzJCo0 zTi{HX0v8D4ks)lRi!z?(KgxTvG@dfX`_;Qg2qL}@#e!l3^hKZ2Uaii8O>ip&peg}S zXpiXQger7Q?h#i<=KIDYI~NWNc)vf%AGfib& z)~DRZ@{scRhK?l2eQunK5nP~XZSn6FnEAk2Fa>T9gecxVz;URQkZMkec^kBz9`}&l z&9fd-t)64OtNT`J{i-6Nc*Ctw#i0T~VJu+cZx*t~4qWoKio%{GSI#*5-Jth18EPIC z8=}C^)bBjCE+zz+g*R!OUn2C$x4GIsu@^?VTK&TfMZZN}96Z|?9Za%)ih8ylMB&l(3m=E(7pd5ord3+VrGf$d1l$VD25JBlLiiZp zLbE{TRrNM6^yPfu4;|uS+vS<|cUH@fzli8|i}fg5rVgC|RQT36h`h-pX&L@&(T7xu z)K~etRy8GqAR*#z0lN^NTi-P(w16Qn1zr$@{a%4sq}2RYJf2PByVfzS*Y)!p21FJ}cMfv6^$ihI8fWmIS({>Bo5&~>5U9^4AcMOpw9$oQiEp24V# zTRW_L_1j+^6V2aDo%d1n=VWRZY)Xc64t~t{5#B!lW&x|ym$vD+-A$NZ)TB}6e$88d z54oQ-ddW)7$(r#cj>p%apa{-|De!|JbHjWzR75&5_|L3wS9bKKIr%nD=AKtX6jsQY z5%69V;hy74k2-z7b+{EcKj{Ea@X|f{yVr)l-Vm&2jIRoiyfrx8o82mITgkb;-_Sb<4SwO9exJbhs57kM#g3aDIpsg;u1u z7H&VBzPx>SgKE}$_BH(~-dv4dzOw{F`C+Yd7?By!`<+DssiMyQj;ue%%5sVxgqWD* zCJ>b2$cT16Z}{Q)RPtYslDv3#X88ophbahxAl0G{7q<$1Bzo2E@9JCXn>LXyyF6t9 zt&So$lFtlz_g*R(A?LuY5XoQ&KtT*U>Niw@jPa&))%M7PY+|+SgRL>AoBMH0Y64>`=9v@5c=N(H8Wmp!C{j@v!_gP>i0T;j& zgg_9yXSj+BXAo^GrCYSDLn&jbquH*nDnaYyC=AhR%)(bUstjAg;8w`dFb1IT6Yb<7 zR6(aQ#-O8YGvg$i^qIJqTBQnVBGqOq&u`0SenjfL-^~COf`t#Wj%eE0^HhR|_eWSmZ9Z@f?B6hH;+m*`a;waciCZFm3R_91nRWSS)) zzi2I(E3cXaG3Cr&Ll%C3i(v|)7fmCV%z7>KiIr}Jud~zRVEVXf5GE;bVj~_mvS)_v z3awtP3w}g!D}aYA0Vv=Gz9xYxfSiOQ2L$Y$15vZJq(Omk3hfQ@bG&D}-0-N z?>o$SDno&iZ=6(lgRJiE3mPGOJE9O7xxz`)nXis z2}Rx$aLO2RzH-Ahu$-TgyG0mLp2_MFTo!Ycg;*K570QmR0Vptn_ufDikmu`6on^Zl z41f3R%nVX-u2q4uC?QX6)Zv=bfkiH#Ap|l+POI&BhpzW_!O?_9yRbVbV#r%8wU52fFV( z{>@R8%dN|}G#|`iYv1dxrjvL!Z5cH{VT`eM>#iQvH7L}9%U}u;AjqebGsej+loUDL zV8p>G5k28AXiw1ZBi~1U_&%b%LsaroLI0fq+zLZl4geI&EE6T5SvZ$0ZCTNOR%k;C z60^K{H2B=Sj{T;-n&)j_6|*|V5}zz-{juLmLS znHjH*+O9$22>c4BAPIu>NM`Ug3YS1a?Iz~jsdL0)25~LLLdn_fL?eeSB8hA-6^u!i z;8y7IcLJcGgPi*Jc45-A@EG6ZdemZ^-cRb1w}1YSGlRDWoN*vyh>LF}-%wqEORrRaL-@yK>Ns_TMY8OM=T`3U@(}j!M1zF8kiDys0iwAFex4~syeEospR}~3e9Bu{F5*GjpG!-=(&@4FMFb*5$?x5&2!&~<^C6K;jD z@p}Li%*6=)zAv;d{|GYG+;~Vq{#`1uckxfm#8X+MmbaglZpqZOG^^ePsK6wFhV44Z zoIdtaP@-8v>yyHr;!6G){WP%!N{-yaeC}&d_yDeiDM*7Lw9(Tybka^{#PY<}oCmoR zRdIrL7eBW6jF>SDAo3~Qy2^r~D%=WMNcaDX!et+^KWGRDo*LF#4~!A^5D-v~ww*4r z@bU=p7-E#_H27tsxIdhBBy=>B<4-NbO`8g5fRS+pa1`J+=T-NTm}27Wk3)PwWgnn zhn-khp3A5fTbgJ~>*dKZABjq~g5?hP715<&*X@pThK;(w2b+o! z*1z`o5Ac5xP;524(rdZ;gYQy+TcOg-6M(`)R}mkmg7j?q9^btX*W;pF$D*PxIB zu7N4YfgmY84SsLvN-UpdLxQFfF?ACiJU{s-WQCe`GUppO9!6a$`&rgevIj1!C+AAn# z2A7N#RXrYHMVjsvPhgcX-3wLi%zPXMnqa5*rRVu|$0RBAj+>)|N%g;1;G_fB!4wog z5J}Ez0#+1{09PL==E#QJ?{;3#;^pr)p)&1ZVmyAeiFCCtJRpTzL3Zge00oX{w!iKC zxz`tUZff;Q*nLxCiTbp57RKiBS%x7~lTrm0xqEVP1)xGBl}Oe&eu6J|7)QW^+s7jQ zf}AJQE6wJ8wxzYtPmcnwLBRq18m6EKg6yj-y~}(pm#-jAtMu;dD|Jd!`**CoKbe{( z9X;7V019Ye4KJv|#I*7b z`{-VAUJ+rtyUL8XjOdK51x1LXxJ(V6rGldpKm|?97tBwp%M;R8v}2yohx6oDwfpx< zhuBeSQfd(83YuPn!Zx@8rl1UhOcEecxqr2y{o%T~dy`GJe0PiDRl#*xb`7_kt*t?)P}7=S{ip${WeVf7(O`p1vD zuCE?Y2Yh4Y#J|&dc;MFYXWvx!u_@Bw!EJyF4a2oxw6uI2aV>BCeE-u&R(9Z(^$$I* zkWrQ-=iB~6*YKHw%Mbh(rl1OfP?QI)u2+Q}d6tiHVK?6*>PM3CD0C2iU9&jL7++ie z>S|p;=7C#b_v2Fl3N#JUim4GVJ-*M#sdc)qKp+FR1i4 z@~PBqQqRC%X9yNHzO~(a9E(k0g)YD>n6H5FCe(YVMJj$juSDOQ4kdsb#naYShDN8x z3JK}!{(A*(6mSzvK^+9yE75V%`Gi6;?1!!1#PR_9a-0BvZl&D!EC z{G}utdCf~d6x)}>V9487X2l#c$TR)4CjR-^H7KZnn_&tXAc$OS{wK$e{zn27ppQSp zc&ckCY3}rU^0_SX=$%IE+aO#jnB9I2w*rE7Bmf1cM9WdALZ`EX0O@Ekg3h$F6?^`> zx9l0We3?JISkifqM~BkeUk@+~b>B;0%h1&~{3LGNjH&crqrqHDuNbn|ITWP#cJvUv zhPG_nvEUY%f+h$e#6GlW=A;^UR#e_LWEFEffWpbTAvBE@u3qA?G$3Sfl?B91xD{gK zq5&w_cR8s+6&`=$Uus`Vz@C>^%F4F+mXKjkQgqL!@Ra{cgRXw{bD&oU_2k$@j1k$l zOtw4X44l;U_MLxvw{*v{Md2bz3Whk?UPBfpz^yO^Ef6F-c$esgP@-&UwG-x0BSJgU z@hMgHO@3WzyaP)6S37NzzR}$G7~xc6SpbT4KrJXE2i`q*>FB>`EwgMWfAm|BRa1dRlDiEYIKBXA_%Yp5GwMVd*Np{+lVu5DD_ zE`IQtdcWma@Zte~%^P~*C>I~xBG-SP1s)r4J4`_b1WA1vQjkYBA}WjTILfI^Q_$=5 zE!JzcyfG@R=SSs)DgC8_k-G!jS@_P72teU2Ik6Q~fu)nnmOfp$_NaS=tQuQQ4*dgD zVySs*;$t5E%v1-)2!IM$nSNMuQQQQe=PWf|2)(W@$fOP*Fi^jsS1#9)b7BNtgF-R5 z1E!!0f*8b4+MpV1tkshjU35&|r`>V)R->I6lmubsVm~+L&A(a~`uyNlh%!h9pkSgD z&kI#JpQ&57ux^&;S@7*)5s@7w`Yc*D*S*qN%@HCS9Bo03&-vr6O2YAS({~AM zcs}wp=QlH6&6PrD1KbLJVW|KV7Wi&tLKRG%b$SmyF;pLgQNrt0!rFsA&Y09VW5Mou~A%v+C!eKWLCP7J0S89{hU+UVd;FOhF$6 zNqF$wnxFo*n$3VmEyFWZ<|vMkd6PcE4avRDhi+~8cP|wTn3>^LsAzl%K%tfFXbY;a zprIz#Dn6g+iqR+fRNWPiaNRzcE4{6x6dT`S(Br8rKn3E%^$g=A$EC;RviBcoaC6Gp zMh_9u+!3p$$;-XRlqPl!3Vz^sFa?8)mgZyYJg3^<)b%IJaf(L@$Ig{R7W?Kb7`9`H zDUea$m0V?^%oc71=ARh=6z<^jWI+`$2nk{jZA3t~K91`iyL>&gwa!~xz;o+V^?Ecl z+|$(nP$8s1xG!Asgi2&JHCH6SJ;LbHDw1c~03Wgxa2Td_A z3|@)pnPW|&HO~@WdjiBDPwP*lk4Fk0IafbSyUGGK{QCw(FdrImQc? z1E=%dnrEeL&r_n+c=$C%Bf^nDX%(Xer@I)SLY?zF)z3BpE2~%{2Gq!s9<%t5NfxN+ zG#EyNT1xv~ME!dOJ~Z%qn1T@q@&nf+(uZpzyqHBn)oLE!VD6b`z?~zK!e$I#DV=WL ztHv+JW%zJsVN)jufWjLC{0L|k+VSqyZ@M;34t;M8KW`8lv6g-Gpr0&mayWk4FsVUY z5TJs4Y#RwTws0u&m^r3fVqwHrjmO94VvkKUn)uo7X6|oXgMu2k2c}>Qf_z_V9=2UD z7;1jQYGw9Qi(ZGPJ?cw!BZur;$jAJdyrj!4=#RkPqEIw64}ikQw~RNS3Kl781I^#g zRCtXg$O#R#NXOTn^OSvaLqczs;xe234Rn{sbzUGXI81OKWayIfoJsl_U%rg3Q3a=; z-Ee=tp;m*Rq+X4Uz3&GzNpbAExobrSs71t*v`7j1eeSN>)dq&Ph>_7SGHJw`2uuBfW zEJQf*;@NI=)!yTXmSy!ZFv|025s`~z9OyoJCtMJ_D{&19Q{Y~hf++~1Bvxc^#dqfU zN}kA{k_U;@pt|BUQNhJTj{*+~ENR-S19(Qf-{4lr|5*e;A$C{i@4NG;W#4#*+PEoW zoiJ0@944QeJIB-P2%MF7g@oQYQVu@>Dj?08ylu8x==&D<2P}mBoehFg$fiT3rJUx} zqH%sh;nu%b;HL)n!4%9c-WQ5b88}m%y)5xmg`$a{l&xw)oFAd_ zpkkb9xD&XBqE@ME`pSuixP)R#iCsM-(a*rGaL3>k0EOt3t!b#jL0SS<=9q|d0(k+u z-e=4OuSX&CB);U7RZaZJ`Bh*JfLR#pQP%JW6K7ReNa*^0qG39_e~VE?(4GV-Me-~A z>rA|BP$&ftz!WS%kQM*EFKD94b$9PZ#AB0K2VtJxdJ$ErwW7)dId#yWH-vF8ga<^6dhA+`8oQ#B|=%YCM4hm02{R2XSx(N+A7~a(YZBh8;aZe<8Tewfh ztjL};@y{4KHPYU$YiG@w_tVkIo$+h9$SL3t9)>AcgCPF$U-Ev?9TGiES`kiJK3#Mv zBaPFbDV}wiY#}0N`~B{+BI(=8!mZ%J`WlEr$M`xA6Gh zGJefM$HE6T+;XO=_q+hJfG4leA<=MfUpwiGqMNvd%ljzyvqCQGH=ZWbub3qW^R6Ka zo#2ZDDZO1F&{JzqYnzL4=Eb~qwu@Uh!)&LnqTilWvD_H4IGTO5%&VPO>$F%Ra;ad# zISsc0zf}VO1?(ev251)C``lC(t6aaL(?*e+hL?$syxBzPki@Hfov1vN{2=}&K!xDj z-JG&F7Qj!>+QQ6e{9|0?+ZIsOmtRS?r5iq`D7l8+e?fHcCzygQ2+}(?+VUI~P27et zGHcwApL2Wg<6A}IT`f=o&MC%2quNUa<5WYq6~vP-ZngX$|NiqhFuX=wPpHD$F2}T* z0F8QUdW7m3hpHLsm{7N(5=B+pS0ayAy9i@|3Z==vkZhcX<3}Asi`r;9&(8O??)CVZ z9OGKMW{MPwHUIl82x@>wU4g0}FaV?s{knA-mB!Wj_3icpK>_JyuL$UY@ zNR5OmDgTXn^G&Y%Dnsa#2{JoUjP_q3mkNeP@ZTb#Ms5Y5u$IL5_f*(PzFj}Qunox= z_*pC4y_^r0&)dgBP3|k9eWK7Lvn5jlsBprEF8A7d`L+9=0uj1g*$!1TLwdPLwJL^B zk{QKm_%)o66r2H%!4w=WvXD4o5dRIS+{Li-i*fqOOwW>}zKpBJ3kUv`eD$Jc;VT7= z7Pzx;DAEoY8edFWiq1Qmq+SWTiIKDkV!ulm$VOrb~pu*P* zs|>C{%W2|(dzSd)G}ANbC!I z&s4q&k54y7vRoHGdEzL1ed&xo@D88?Smhp%3|iR$TLmpf|K{UD26y86-1j5wpL0D) zKN$rjUxR`Jcmk&2ba6t`-Y$#P6}JU1(vss7LioxZ#Oeo(5*}r5k){d?Hz{>46^xon z;8qAMeg{ConbG!dTekQcK`!fhqU-}i_cqXAne}F9_$cf37N(LZy|{ zj}&bNnk@DkKT*v^w$fhXZ8&>fRiwoZxD{CE-UCoTR?YYT%|eNksE10|(>I1)-%FKl z7le|(K2h7mqzbpjTiBwJWd_=cik6G!yAVSjUR5gf)IN)q16I4C+9wl371psXk18`& z-fK|U0Z+jcTrOG^ZaQg3o6qEvQCA7ssL)~3YM61|E$+@3x)Hj80p88KR4^cfe|4rL z>jj`tvJfc@RY1(YWnkjpTc<`0&U!8Q_5IY>4}y#F-%c9Lkyvbhg;xX20*h&(<*sa- z#%WX+CZcY&%nMnEXH_5Wx<~Xhx>9=P2LF2nVPWtzOu-cd={h0^D4wzpL_mtpVozs% zYLtGyTtAg{`=<2VDCRt0+*KA#1K`ero>o5qh52XJT2O@%XUhohc$S?=1v;yms>2yx z&KcwqG)Vp{naa=kHf6K`6+F+d2Q0kM!9&RtLEz?Xk&$FEb2Y-*cJ@2q;z#@hlh>dS z1fGE@+`HKEd~}p2XA!@C7c0eV)YF3nFNtRJ8TG?11>VdNUGpD1mkL&|L*Z5!4I2cY zKg2rsfi>I;X&u7=6xhR5Tc8R?ZJ#E@{7wEy=a3Y4$V5edwwdKv z;1QZQ+}vPqKC0*hsKC>Xz!bNy9>qqtd@}LMa0owg)Iv)!M%e5<7NxMT;Q7B-5WxX| zfho9O3>^7x9yecj+^fjy>4~DKeG zDJG@xbaBuL?cHQ=e9EZ^g?zn+??@tg;IA-+`ydFp5habNjVbGjr@0iBx7;g_^l8T2 zLT8K|_NOX+na+%t3Pug^D;)EU0Z=fAPauLSaEkm2k+0T}(IznCrY1D7Y`hS5r7H{Qyv4V)2oR-x#4%eojeaS@wH^|+G-G8KaCPy=yR$TOMeh%RhbS*VDII}1r}695!qHKqQZ z3QLY+joP*|wB-Fk9*umG`A2Qd(i5G1jS%xET39tf>}P-qb9-V4B`-ccF$mv#g?rw2 z`!VDJo$p5T2o4cRu^j6I;%lf#3*c`sg@+&r)jJ&rJhN2YK*Aq{i6&xp)-EJI%0ZIZ z+yWVhUB`^ZmkNeA$>CP;DVq8(3je7I()Vo2o{KE}Zxf`&7A)PWfj|5Gdj%GP7)1H3UP&nCfp+yU+bYE5eqLWr)}Ll(}#i!cSRi!Q-N z!d~%eh1&YdV-Y^$Yde{nD&fxjilV8S;IdLi>n^Gs=63^_r{e?Z2Tm0=>aOVZ&Tvfx5#K~3p0Pu1M>^jVsGTm zl1HDclKBsFj3|u#dj&Ch@OPMkHwYqs+_21tr%beaON=R`C86>&Yx3+vl_jCw7joZn zyeJp0vf!EzcSXV+Tm+!-^HoIOUxkuqxTbdu7QYt?VV4gSSK}uSweAEf5f8b12i43{ z0X-hiAmp^3h~dZkEAOCzi9HS!%O_xW?(HW}wBymd3NCHA28Af_514`v2$K9^Mmtxv zFi8u4t!hLuN(EgRf7{MG{mU(xUG6Ol{;S3>M#0N)DY0Z-9_Kk`WqVM$?pb?6DbB$!-$DruaC=ce3S&L%FWGyoOA z4YJzRoAgUb0%vCUy4%R81U-pvBO@ZV4Mzq|Dc#r5!(W^nybM!#d@RzHc8u+e@qFXr$zuu;mx0)Pr({RsjbOLm&y`3q{+h!m{pON+N-NlTIK1Kob( z$94?<`z(lCgI8b*ejrGsS$GT{ih$vskvH2J-SlaPZL!*ik0my;HIM#~KS+bNS#W{> z(9!qi4FC!{kGlRIMxEv34z70Fa4nz~wnDl~?_%PfK>xCVt{@G4B<$;A}HkGziWu)QftzfM%- z+QlJ{{G4Xsl1rFZo!K?!x3ijreh%AKhz2@4h3( zR9=I^7I+P&;17b7BodzU2NdplkUfm$47cYQ&vNSJ^~DkJJv8*1Gfu9*R4@~kfLq~- z;4c6Q+N}0}k3q`cesBFWVz(o0L|G^|CsW0Fq-D#~Xr54|S5pUI7VLJG-gDe5 zA-=KC_9-)j;|!!ff1>0t$lRNE9M1Y$^%`bDN(h42VG02k?K)X+yO)o)yt_a8j+q2Y zs^&v@V^k%=XlmTapOSp@--K5RODS+GRD13MQ0O;C{|sH7d&5o^t=KzuUtmkK$u*4R zCGL?9qY1T+p?{0KeZYWu3Q(bhRI14IF|KJ+DQ%$eYiZ>IwfA{w!eF2JrrVafg4KKf zJ_`~7;0>5UAP7=>BR_R|J0?A3!YxM{^<<0h5&w#}*U}=5EPEochScGuff!l?7>3#y*CpXrosvLj*`SH1vLVA%hHxc?o~ z1Bt;jcs*;X&I)N1A_LMvJ4YbRYI)^x4J}6`-hqF@6oNpI8}1q}_MY84IC)hXfLwO; zwEtdRRJr@=AI6n^+62UCl}iPq5AZjN+}S(;puoXz@(HRiEi-uXJH9Axz^|F#n zoHVg|7bnZ`XTVU1b5idBK!t+9&tjcfoyglPi*9DmBfY!|r65h?R(h`YDDjOxe!Ye% zgpyd`O_&1cVvE0~w3^+&Ni$3Y@@9_rrsa>uXIjtaNW;}lx1x9=#~y!+j)m>Sl>g)!xd?6!R)(Q7aDHEorRT>a{vmh z5s&^}Eq|ypi@Y}92%%GytGT^>Y$PiiN^Q2?ZTnW{07Kfa9_Zz@L0q@}cX?d9=|W50 zZ`-xIIyNLeU~#Nah=d#{+%J{DzXpXl@GqD`2ngb8O2T(*n{`gjBJx|T+ zxcQ`TY^*Q>ZtJ}(g^hP`D|}c%K>9!KC?NdjOA1Anq#vPKc(~`|N9TB}yg=ZZknYht^)*B3YHn+I@ZP2ij(dssrxMy0zo)8*_GXShea)lMKO6$CJ z$e%+jzySs>-Mgk#V+<$GwWgYNSdEg`Fl6DbJ9rnS@C*dW9~n?Z0rlT|jy`ik8^Sj5 zQ1G=TVxW8H8wy{LzQd!drm6b-+;C^X+z}Ok0%MI=I8?z`PeIVT>3tPqZKIR`Lt|3W z!LNiIC8f}TN@jh0YTp`w3Ivviu7zKgW)KAx?1kQ$#0pTI=%N3Qv|hsGBHO1Yqa4--jmH-=zb6YZF{IJYuBPo8F3Q zqfJBUus>bz9=$~%_2k?(70F)h;G%Wi3Jod6fPUeh5c#F}_Ct45r8$bUd*$tjHvhZD z|9_nU_|L<4?w*48U<%Jc5XV&gHGE|Xrs3Lp0Uxu|9o@-0KGmIWTLHNUr9=0Hur3u0 z8`|Mkz+J`wpnyX(`5mfoHZ{X!!4c{Foh)eC}rAFC;5oBt6iNH&N=TDUhHU>4rv ziJM@Lc9A7-6u#6HS0csGq$+p%)C$r}7Q~Y}*QNOP3R1G*eV9TR2qMrW?&B*V$iAiF z93Qy6=fz!LVf|E?g}H0wPS$Mkv#VBA`s47o>(pk#2B2_9EOHsDFnfFU^J}`DY-+64 zWx_-}Lp{GP$L@8qY_AtHlDMbCK(i2hWZGEL*fMCFZD{LrHmXh%!*(aUu_f7 zM`reGP>2K{z!btk5dFe&YF1%hH)SagCwq%KF?9&$h=SjXYc z!WTze01AAo589v#y78eG&5qxkE8WTK-7#B7M~a5L?eQO@c!0=D{l+0HxpUW39Y_z!qI9_>XF zT1orLnE5re9-U&RrSCp%%(~iN&`*KCB2^aS15j`h!T!6;GpWOFHTA_ky>`XOEj#Bq zxt9(?Ix_xm+?P|v)2mwzEdVQ$XoNP(VI18!=0ie>IOLoMvC^f#Ye<_vX*}JMm^nbIrYH>3$6gw%}u!LKFy6ddFINGs>By_w8_&q0z$% z3zU5WE8=BFe}ig$!Y|A7SF7{KVz?DJ*lq$)@Y2Tn`vt?IVe`fCzGx$wV3>qiI9S|3 zI__96@k7#THnBKF#vl`*LM;Y`|LRLqhP0RXPBbFQwJ82wpf5~J#G)!^$|dYow1KE)RQFwDysO@sR&(-9&^&D^0B5m;!dRu3EBAZ|NDw0 zBL+T$Da3#v-QO!}%j$%8eok56`tXQCBwyh4Ey4RA&tKGVF8l4xTn*nb^5%nE0qqwB z0EIDY`oEXg1S5NVK_Vx^F)hc7p?CE=DI4qu4Uw&^`FQdpmui@&04fBi|N7%x!ZotC zO>p;@P0yG1Lx0qlg&(yM=M@k(+%~U6Aq0F5Q-}pY6cMo(6xUtCc1|NyxAR}f_kJUZ z*wOTre*E*k)Wa_!zpt`Tg#ouhI3G0t1dacD)d;7p0_6>&j(bPzgWT+UaQe*0O= z%o#4-NtAv^UYM#IKm}fste=WZBSwg3@{d|P*26O}p89N}7fSyP4se)TU&zttYDA4@x zm+${)QZoS}0u#RC(o{So2`guT#zBp&0{7wI8ylvm$&4RO5f8*pZngGbL7W~Nth zmH{f5OdR*GXH#y;v$zDIgMOXwf7P-ZWI>a7#^J;6oC3!9#|jc5NU}s1lhI%d@gT_5 zg4(y_fb91Ts`;87?Z>w?c2Y*W96~YD-gq-t98_6lFQb`^%clM&d@aZP{7lx7hUWyvBFBXyn; zyt|r;bID+$=?FJN=P3gKhJpZ4wOUQ_iD4|pmqHF0Uyx+ z%sI{gWKaz)MQjjbQRmoiOYKY$X)`=n!s#@pv?}@f{+J7FVtNe>dBKQCFor}BWZAms zGo#Fe`HX{elFh3L>cwLIq+ZG!uarqEaF$EMtS%W0%(LKTu$N*2!0@yke*((Trt=~P ztE~3EndXz7_n3Yg1>ovPyE)7nhH`Pk$@=FhG)JR*;0} zF5(*QyHs}3X({3w7}kRkkzou;APAYEV*X1%_LGx`@2#_pYVPGgw3bdqA6DT$ZgHjH zTGG8LN=_nhGiW_!0l@Gv)IJT$@Ea2SHKToZ$8$FMK^^xxYZ#V}Z&HqUCYjX8v%9&R zK-&~%U>fbZZ;`Ui+2s?-}Iyf)P<*49OSA=lk$c z%QAO2R|I#&S|dFtwm3q1sF>K|t(-W9)~%fqQz*mQ&L_dg zlRNeXt^Y<1SJXa&e1zNGRyl3Hs17ELe@b@%{7e!RL5rXit5W>&a+LAlb6Ye+*^Fd`a^Ar%A( zNhMRjo)MWLZ8-HT+TFvrClY@HV_LCUok6Xo`3E8MRZ#-d!p+d3%?*HI{ElY_l%c6l z1F!!qK@o42!G$ldvd=^cH99nRO#=gJ(TFh(261zd(V>b=Sh!| zro+$udW$K*txiYVTK{pr?9meny1W`e0 z&Ec0jRPiD>cp@U~X$u|>`tf;xK)p$C_-!_?UD#Do%7*{ID$N&u01RW>2V77F{UV6G z+Eba#4>Ue(a}z44?>645x!Moj=n*0%jcC_l2gop{@-rQa>_IAZr-HTt!IvTX6Fq_L z1RUy{@neclf6Xdg14DW+A_j~h9R$fK{>fZ4VXzu{AJ2nM5>38bw5_Mn$Ah zLjf{;Z;--6HA6s&P-36cgz#D!C@xS5tL2kx%b`0|ZIb z?8w9bI7j`G!6IKDZiWx#VgMM1v2n?v4DzetBznO)N5%Km9@cT3mpQS6W^NZ9h*7!9|1n&k-LK%kFrJW+hiVySD+D~Zlsgo$UV z^em3Y{4_N3-9>X#HuSdZ*T4`D0pY_La=_4L@prQN1f}xLarKIrCu|LAtl#T;UusB} zx*OJeJ5EeqrD0SA;WUin%K>13{%-AuF*M9|XLUiWCA6JWU<|uw zX@TJsls85hk-EDiU%aE^RXF@}#+BLODqX=;oe6Ytq^s4Y*oIJn*Hn}U716`56Awh+ zYV@&Gv!31}O6%`l``2SsFV6;fMhJ)y&hX~4)eV;}$<>gXjXK@q%kRZOlPReEa@HM7 z8uC@NvetZa+^aOWH6qL~22}#UfaSM%0Arwi(V1i0j85)F71PNS`TohfrJYD>zLuPp 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�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 z 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�GPWRO3V}J86 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�?3J+T7Tchu`-vK+Zdck8 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
    EXj1pd*pkeUP0gNEq2am=X)n7{+^Vu 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

    AuvRvo9O$WQ;n z${5d2o)f5-3@(i*a34y3hCTooS^`J@4r?IPUK;cxof-0b@M!$uc3nx!%c&2sN4FHU z?1aL7<^nzeWYELJb$x7`id?@sFg>cf!eZB7(@VAC?%*Lv)ua&>Q-=67q+vin{xAkI zFf>>AyC!RCO3g28vynGbz5Y85i)1Ny0wO(u2L@E($nlp9cC}V;Gelmm2EgzQJ5c{B z4eH|ibT`K2ygjMyR66=qkYkkd&5tx5Ww`JPQ`8QcvH)bb8={k(sGc4=Y&QqSZC?`W8Ln8454f?*+mb zD8NwkO`!)GBl%_|ie&yV%+tM(`CXPg!VlGXzldr^65;$gl+?@l;7$Xh0ZZn;m*_Eb ziYHeLUzoN^og*n2HihllRA{vd^JSpn_we7mWULR6%C{B!3@{BK=D-<-`OwA6kF-DP zkk3d5TAv+h$xZ~JZnk=8p&Ah)o}v6=)?N^dff5Ww?JW%AY0Z={FlT%4`0mnb%$}>X zdklkiK&<|3p{s? zE4kx^g;YYbi46ox0Wz@Yesnr;({1EW3ExJ|A=(QkH8)nhWo&2SUYDCBktBe4hMH#( zP%w;v3Je`2fA`4v`?PdrmH?812LqV-aUCNC%i=fElNHg=#&h|Xhf#q0owIIOJmxSROLi|rz`6bi&MG+$gZ34t+CgP~cu??j;j_1}{399Y?&RemG1 z#Azz+>VIm0OFJp9ZTF`{+w9T7%^;J|1AxJ1VSVz7fqPu}uJI3!M#4t)P1oJkPMbm60{|HakBrfY&5pN82IuYG)_e^?$`m2Q3874GefIf|4x0`H@eEx! z5Kt(Lfd&kX!5VXNPEI(_kDD}P0-Gk_OzGjK^M+O9pI4}$`P8vorokN}18xR&Q`D?~ zuML$0r8HLzDmn~$QRRzE zJoKi6#pOxZPfsM>W(h*+>>55jnq?BiGYnkJ=njK1(1M|loKEnv#U9FKzs0I)o&AE6 zK&9GSfJ4}~gOR@F_(kW>O;Fth_!%AwJOIG3fJN?q#o%8U+lDHwtzY5fH?5JJ|Nhwk zxB}HNPww{gl$7iwod-Y$&FQziGGnKKGlbHCGQtt*d(?uQYxixs4bO}{_&>a)LOjFR z#ZAy~7y}&`nrPwfa!cVlv&aqs(Y!Ix>Uw_t-i4M+qI z02t~GZSb!criGfXE#KoKwodN8yR-D`$x|5c#qy8ND?M#WTC zDHKCHN~&3$s#S8rS%&bELA}ffZieLTYyb>r-x9^H800=G+uTj=N>rsd!e#6kD{gkT z{4{u1njA7AjsM%&jsRd963q15nf;1C%>}D4>CvnHAi=$-P%9DQdp89we<0)ZKHzKdz_-*`7HXLoOM#klf*BAfA{8 zzz_`<{&B_dS%rpGnna0xcbcAMDbV|r;}Jxfv%mZ>s&ISywPt_=Kn9dIAvWAX`85ab zBUGWxk%rlv_BYk6FahG2; z4sFc-WWuRMI$`6wy7^~jhOR&SPgpJ6Z-4yv5^X_d{CBLC`OV4V5|j~YrTyv7)+3N+ zNE+|k{zx^$HSm!+4&y}&1x1(q;#8~Nn_TZwv$C!s&>+4PSyX@{!Nv#iQ_-PFnJ7*| zO=g*yh}6{qObHC>tpT?)ng>vC^zJ0Np_ijWea`O4kvD!#nkKbZAZ29UB7R2^>7V}& z@eI57AfRX%0}~i(PQZBm`Rw4=>&d@S_U3-=P4;v(7Uhp0;ZB8#B=235xlDt>L-;38 zCf6tcU@#lA*Skss{}OSGh?Q%R=!YgD#Ww=#b>@xo@r(4s!Qb8JdtS1%0A!$Ib44-d znPKl?u{-CpdV-zv0!6)r)I@td`nM3pbFV)us>b;?cQjr5Jke#z^LB zAe@2k+HVLb7RJDQv9|kp0&<67nEOt&1AoIJ4URy^1HwaFCBc~kmnf@9Bdh;0lwy*@ z|AaNE`YQkiHn;lFD~1>7V{7N69ImRK^r@10gl|r*gRIk*E9*o(uN7yboE`#90}V;6 z@Lpy)#pJxxd~6k$2f2s+E_=x!F@1G^OyjVn8R8jk^+G^#Fb0;3wcToT+5Fo*K}QeK z4a?a&=7SFXAG)ReG}3JdjQBnw@cS|iSt)yPr@^vy8vuh0lGpqdgU(bJBUbZ*`r=vs z8xd0qoeKIExvYEgOHYDI#Nu%t1O399eQiERe~0sJs`R_Vrf(=q{@G;~pLJ65zl~oF(n`##=r`O;^e&*?H-u1v>Im0zx)6Yulk@e|LC*gg#^y=1Vd zBY~TN>>Eq=znAET%X0Ep3>r@8sadiAERFht_>OMA+Yt~@0*ry};$C#DD)YGn zFU|d`+m_5)?X*WaMY1Yoxt<-5c+%R$^q+fn5E;r z#}8WPI71wSGDq2`k&LX&Q<}KX?T<-9bpbMvx|lgiqe2=#$d*w1&Xy}IDlZh%GT!MH zfyg{sq_~avu~vMPju22HjDZ~t%{D;crX}9GT}qURamw@63*Y2@tfL~9mgIYC>w=q* zx=RMLDF?XIK!Y6*fWc~#;qOgQ0h+qAJN`#(>E>+f!2_1|B#`s@P|A6ndz9UWY#3ZX zdst21TU-6^#+x8fadFMoC;Q!!RZ66UIlk<9mS)_Ryny&VB|ZiX2q+20zyXFWPKEBcME_ zFvy#PZ*9#W6_5CBCVXr{5KuCVffEe9#bC*imwS+sWWm^0TI`5 zkTCV1OIJ?X@Hf^M8{EkG_u8PIPye@F%*b6EN|i|*LH3ygZ#(U~xSdX9grB!~hjwZI zV+xioXMhZubu?^=Ka=G!`{E}Oesz-XYorbb;``kXk(8PA%~wQxgA5-xH3XCbW4H^3 zo~dV_sxg>FhSQuc>5GTC54cIl?Iz&PIul5}>a7f}ygZZ)+wI^^!(hZi01UEf&;GU& zAFU-qEBbh5XQy2Eq4GCgHB{DwqH4R@`pEHddMCY10my*n$0ILe%FGoSc4n2N_hkij z{l!=;P0;o4!K4z?6|C`y|E45}1_8Z?F>ryQcI`E3NR{%3KPmjCn;py)Pm{;AJa2nw zeg?m=2+Dll7a5NC%2B=liLim^5wlK9kq$ zHgp`q^tzA%GAOLeu{~lk`SS3(m(e#GA2Tst-6G52;HOL`LfHnE}!Vd1Q{rd z;T{;OD?&>fey`)2vzDa6d4r$f@ca53pa23VK4Kl+J&<7X;_r;WentfK{kC@&vDrfx1pp)HcX=afg zoq@L$5loE8PpS`Am7r2CZ6Jl=umEE+Pt2$iV=DyJVo_tXwh{g<`?1_6sjSh zR2T!##lC2XQly;L&|hQ}94jMB8Gaflxj%wy@uUQPE}>fCxc^x=c4oT*H-lz6S?<4= zXzFstx+?|^=1iAcBu~{?;~k5C(lFdUG~Ll6{n5u$fd;*EdmRtx#Ck>t?5(Hc4v>h| zIL|TmxH($iM&Z!)e%hie7B*bbC1k`isAWPxX)uQSU}#0Rp0O8-9Lx2G0ZE>r??2n& z6%NGl^Q9=aZa`e|H;evvD3zkevck=9cBl-1A%7@Q?uwz^#*mGDPwOQM$@=8&fv@w2 zzt7)1oHpeUY&tMs44wwMj528P2Rpuwi$*+E?6L7;QDprrnNx@el@le~`m;S9lyJl| z=!QW+=`aRfFf__q3uO%B5PDvvroZBcvgWJK*6>i^$I1t;x&1jQt9O^RA+PNd+zcV= z0RR}ZqI>_YSemR;>U-_ksnB$em96$Wo8;YybKik>sdtX1Fk^b&u^PZbNyYhtcR-4i zcteBKUY+;dlv_~C1MZt@^rAU^DLVRDyohHoc7=d4U<`a<=<5fIfix~!dq)L!er{4{ zypMDkTqZF(2VXR@nv1#;>0C1C*nNhZ;Z{{W00#F_k>#s2P}$US3)dj^1XP)}J4H7A zT>kR)pz{~Bf^pL1u&qod9w37;Q}ro5|HK4}JTc$4VdAKQ=K5iK_V47j7c7&;o_U3(9P%a*%^ohYc$(W?GFYtP!OdVx ze+Yn~EgOU5ih&x{c`UxzELq{e4d;X9^r}l@s)?F)&{HzyV@d5sZlFD^9)iBwmJi+s zP_X*6h^2iyFDZ6L^^z_Yd*qfb^P^)a3h@kfst`~Xj6vXH9Bwnj=3bU!cR-QcTWYyv z;jS(97wyhI1t70T-omn=rb`Ah;~uyfnxgOK{d+Q z5*^|hT*M)uk1z&7Ff+fRVXFS+!+1|jpS+(4*VbN&w3}_GQ`pE3K zb|Xor;XJF&wVO9hHBx+k%H^F45uKd2&sQV;2M;qmxFDcx7=sWP8hdR^bM9?PBQ>** z&na?&Vir^G{y^Ltiq~;BT@%UK6fPO8+a}>o17Gla01O9r_r|Z%fc7Q-PUYu3DF>JE z{C8--gG=z%RK*9rZ;s;9BL}Ki^Zb^7u!XVezLMBvoZ^Y*~ zAwHlP@oDh6c&3yCV|W0DnsQG+ePrVGfUmt+?QKJ4w{O`(ug zN99=aLo#tJNHnQmF3%46Uir+EXWen{G7bK2@PAV>gJOUB_u3%(p8D_h^iZ2U^x(5R z)WFjaaAKLp`0DJCO(#x;>M!;?V&N7#H2@iU`wpxqTOWx{WkEjq$M|LE;=SOnANIQL z;mqRJ?VpDDj&8mvWC$n^#_$jfok8>Kswquf?5v{M7hA&Qce6<3>Ct=d-p~rM8{T{) zd&%I8R}Oa?Uhqf*U|340_`8f!1JCQt;<7f~2=Zska%uyiJmS2nc_%t&Yo3yG`C2_+ zfDBV)^?eJ>=sJV*TCc1>XT45|Hub`dcILq^35r4QZTEfd*}5CxmWMyE*W&`{orQM>3s`;L999M`_-YO-x~aV zMM)v`x1;4GOF|UV>M_x<*$s{jf1T%58NQ}KXLNhYg{{WV_0(n8m$Km9Ic;AfYIBy8 z%1K)B9(Ze_e1P}~GJGHAA)tI1gXqQGw~f5o7h=QBa$?6G+3JQ{kd2Low1@ZX!)ktIoyWWvs_Bqg}Z+_96N8>PLuKzYY#I%m@VGFTAd>THELqG*E1~D*H zZrE4Uw#V4MJBIaH{x=MtSEFjrgQ{II+mo%UMUt-GzS&O~z?}v%&>8@SJpUJeyY?sv zG17|xsJ8CwF#aNqnDMigO60#Q++@od^g02$*x zwbijBe_Cy|XrrU<9mF#fT=Xdw!WhKCP|*rav8GttdtkiqWEzy{Bv!P-^WU*x#*I3u zV<)5a7ng^UYqJ;J49o5G`Tt&`sS!0iSP7YZ4PlM)ME&i-#g**v?n;{>p3xFXAkG1CN zP&(2I&vn)hvT>;xY}Yvwvz!Yx87o2On<$T0V8y35Qv#R+_^`8X?7-l1SmMghlpwD;NCB)yR6*^Y_9oA)PlW%&4=N{D9|NQHn( zVGJ@C54u%qeS9S3hg!YvljD2e97~6IYDjE#;++oHw;UCT{uzh+Q6(1cG(7(x1c2dz zhZpV@10;KhwKE_<*GNlgB~`|cu8QmW0|mZm5i!OhoDZ+*fIiw2$`X(}FaLo_9>sXO zx)NofcGKb2bK>U>uW9tLZ2JOe5zjD|1Ob)77#@M4KkkV95|qxn7Mp)M@A3@1fls9V zE)7YkUCll~0_qvYczGyAcIm^-faK}`fPs%05ATX$hGoFxNmNh;^C1a35u-q@oM>az zlrhK}f0H9nMw1F3;Gu-9?Z1|@tn8mPXK`}$uv``_Y4jDEXHph9&+*0=b^HkN4AZd? zP&tf277T5UR{geva;mVVl;dHOywP?O{ozAOIj?6_CY9sK`JsK646h!-e<3$kCl>&N z<7)TcD~Nun8mF0cV)My_8dL)oy~mx}WQNhI`Ln5gP3`4EPkaC}1RO>?2UL42(g${Y z!->_Im+-gKR&13VY9l*TG^J7f4_X2iA|ap(7{g;Qv_Mq~Z$I(Xw6KWXoCeyht*;Hs z)uUX8-KNN+Po$hH)Gis+(%^sX!y+*YfI%dFSmG)TRTNmudQF9ku0^yTYcx=TcA~Yk zUZv+)znAn5QaOqO`Y?m?hLzNTv(zm5&y-1yi79f*7P(*IbomTiUr4m>cc`u*J`L-k z5KtwIK@JSHrs$ZT&o|-Xa1>)UYCkByFa6mUb!$8ISS>slz2z;@C4+e={LhpsxyTCt zy+muQQFLB0&{BM5#j9+jJsPc{gqkcqwESB0-9^s%plMJtUbOgPY&5Vdh_lw?boW;1 z`HTa)sWxp@+DhY=;XYl9S%3IGPp>jdpr3{|v>Uf)yHcwUrK9e>TU zP8D+5UCiGg+*zvGEQ;9k#{DgP=N{>{H6U`wqfA%SV_CDPSw%*=k=k@oBRAZ{6 zNVe zz|HWJ>lgq-$B@_G+R)-Y@JnS~BVyZaIC5DZEgJ2!_WE*~&TN<4r)Gw!jBwNLM)9|4)F|l7l%>}j6n$u-Ri8NZsF!clZS3r1nLm*xQWuj#O=4I7yPc;AI+ygW>QFM&dHCspPuR1m zEMm^~+E)F|N7!f@jJ_&#YJ@ld8J4aQiwzhVH5=)E@k}u+n-ljYrvUR!c%@81 z0w^9trX!w#?t~g7lxA$)}@r^Yxq$7)v?lBg=NYT{y(-#V~{1u2J29V+7 zE%mlj+NzNj9RI~JZ8te_90eWW9wUj<95v%koiA>PXP~xB!g7v=gyf)LsAQ{! zw1d<>Q2)pfe@IsF}ZwV%TPR}TK?c1?z%p=YnEqHzly@I1NzGCZ|7 zcrh!G?%h8Sk*md7dH7QOZLcX`g{qam=ZSVO1J0*0PTmXk(1f05$({=w+I7DHXBBF;4#^J*FK%^y64{E2CopLOga{5$qYQYZe8 z&zkE0|FgzJM*3Vf>vHukUpjfaSbS=-erWrK zkO4oGgD*De+zueaeQU#kW0uyK^t`;Z_})%hi4WP{m>UBdWkNW;>I1`wzr?^V^Z^2D zf-$Irp*mas?=zj)KxRa~;MxEQ{h&S}1q(8r^f`r4;@$NI^GgOj93r?GmPNb(FmRR+ z{(YL=6vo9`CCUiwyFroG~Ci4dNdmpk^3@#zh^z<3fETiM~}bhbOPA%h?%BX}Zx6 zPtUG%n`TvgT<+HY7)oVDH{oW8fP4kOFdeqDag~O>iC?~vO(=!FU(LG%=`x<9gm*^2r-W*Hj?W)1K~ouw2TXSvMS0=?^XC-7oW_DWZ10@q6{LQLH1%k zNehfY6AYbg!-?P8b4vb-XCq&1G&h};f9OmcM#Lw~C2(?EqkC zR<&}tVh|sfd*trBQTb#$ahy0eiTee;_H{!P-emelaQY8e`3S-a$L-7b-=)Un?>3x?F{2-U{{sKNX z#`Wk5`Hi7Nwsm3ONP){V#4ufhI}OL=?8X0HqLJdD0#^)A_%sxa)D!%|ow=EYf`)Hd zGMed23d!WLGnV8Od{7bw$Ur2B#Zx6>L_WkEuY0SnY-BFqtEQs4?xzTMv+Uqo;~d1N zL8B1@YJ)LoUu+|O;HLEm>tiOWSssOd4i^>)ZkyoKO1fg^UrR&%-*m5C)`pMtU*Tq` zaWnzI;BD3_dc|OFh=!Rrua_<{|E^xZ&XW1}?-J(TNS5cwx0x}Sto4QgGMtLpit5ti z>b~3F!YMUHd+BOic|6K2>Zf+FoP>EI z;u%c7K|mca23;`piGT)E>@&X5f=XAC?@zSw!rSkVk~O4DFmIOlf+`s^E*Z4-$Kg(c zvA_rbhI_*I%B~nZH_=M4P#q31sp^i<4|&oxua{N0Gos4Qamyf;;V zo4ha0mFe^@_TGp3o6ZyaNl35znFN^`KX4+R!Ri+T)CptIyLg(N`RN6tc;_d)_p{z9 zTO+i0IjW-aLIY1*BAX7kw!;$tq#?;0ZU&i5?2>=44d3h&pIm zw-EN~v5$#tDqEbEUhB(-5Lek5fDD?C&Pm5DM3vL3@NOEAdS<9$B&@M~UOUdqt=?s=#HZoSIRw-VV=w?if0_lF%PEX&@Dy4F zX3l##g4g_@$?-!fjs<*tCuIi6mkcJk@DJ4Ei}nD(;NOt-_nFd)-9GnlRrAXi@1%W- zIVOwb%oa)qAW6u5`8Na9anrj2rXlUyQvu4KzlSm90|oo#MV(!hrAVYvl14BudI0x@VIm$f*^_@DhdXE-uZizy1K8LvS$=%y-65 z`2T}o?t zU(K>!=ZX{EE?79|;2Xng=;*-B4;$9`Cd`5#?j*H~iug3dia|jAFa~2VRMjm=h|3wg zQBRLghL0*1F?~ke%)-6d3B?M)TFANg=MsYv4g3$f2U`sRFoZvO_;a-mIPO!gJGreLtFV!9!k) zk#s0DTACU03@IuQ&;X3#IT$Kc&Fv(@5O-j3ILp6`?5Xct?KdD#MrmiNy5HO6Z?t%s z25U3|xDO>p(*ytv4|216uF}9UbRtvnMrI7{xZ;L7 zhTvQG=9PPu*6)!t?rIM#lxxMv(miq@Y(g^^>H4rWA%b{@jElvegD?gYFcfL0929Zj zH*gm_AGx^vq$}xD$x|bhwQ2HRinA!R)5{WFiVA|i3nmC-5C8*YB7^mcA>ezmx1)N| z7b?=9I&-%7%SEfyHE$*fveP=Pa<`(s9m`CHQ` zq%`l@fQ7$4MLa{^8wh9!#$b9e$;}D;Jg6Ci=3s?|F@}y%OSbAgR4eq%uyo-5kbQxU z#$_6!n;79v16l<}*}vBY6AzUSR}74(VoAYddmKvqy_yit{5f+6JF2{f;TNIHqV5sx z!ukLilt$$qKWoWGVaBh@!J*6Pw*_a+P*xQ>Cw98caXxF8MLa|C#e4r@7=zix=wbI2 z)`|i8m_Cl1KO2b?@7wykU+vY(9C1SRay4i0O}S*~#vg&3A=*+B07JA!+uxx{)+O7j zk|!eV(-fjF(5eI8P?oP4*r;mRS#ab?;Fi??0LU;MDo%)o=HYcM_r3rn<2%*@^AGpS zUyvP-l>OAele0wpt_=RF3O%p! z59(T^e}=7EgX-aC5M+D{fT5)w9px$ws|Pjyk^V*#JcP_l$szi+#+~(aa{2Yh?VPOF zUE98d0Ayg|{q=Yd=YX7lH#wiq5lg{aqlUz7qZU6hxGg$iUyvH{X{i4S0gb{K%r6>M zXQ6kwG!>aQ6p+IVzlV1pjrOGA2HWS9VeCNEZ^jExkPb z&-GMf|9Q|IH698#Lr38{00wTY8=xx&D*|Grd)M@N4V6`%WT`X^xe;&Wj|2+|@~Az1 zVXNlA1&~41F>W!s#Q0XA+DNUeN#STZ%QIvSn%diq)l|CbS#JUumnS? z-7NK$zJ7e^*so$#{k!8>Z>g#<+%6aovyEu@P+(2$G7Ua#@K5V02Q!ubdx<`3-3Ys4 z7;5G3v~IFE6_1~-Zb%OMG@4&sc`+%foxxn_U$K-n(Mo zRR&VGwdXnvE*U&n;eYK@t?>*1!-o%lC+9n7Wu0vrUpvBu)Do%_{_l@T_Dy_jE8M?d`w$w8i@Xewfib+fFJxn-t+>vRZmmf2 zyn3?hmhl$WBPH5Ji8bPbUBolYU2F%KgfYClXr8R(pckVM|7N{~{VZoHzShJrb2FkI z&9!fopZ;cDlGG)GmVYzc3?yU&02pGLhyQK|2plw?bp5zNg8F#EWFVh7LFX&mj=C%V z-p{!=Tq&_ophJ@wMY#kIPAH!*#>G0^aawEJh@qIsQ%4K6+a)Sl>1c05Jj3e6u8i+6 z1{*LGqmJyCl0#*(81_jzN33>`m?*A+4k3oZyX|(yRVBqgYj9m8%iw0Pxq(sf@3mnl zy{7ak4NRr;F=nc%PB)6qv)3>^WW*Rkj7(*&9cl)@@Em@!Q3x~*c}UvKXkzS7e$kYK z_1~r*U`i#i!L+oXnabwypyRGXJj3?I=9noMgYCuW;fajEXUye(>?!e4*p4QvqusD7(PNju3j-Ld8z3aExQe}jM#iU_Ks|u6BVfw z&;<#jbz-V$CTF|@$k2?;JMa6tVwKclFGG1&e}* z5FE;vP2vB+GE@=1;7y7G%a(*u%CsJAzcQ21Wpj+@=rTG`bhNn z%ho2nl4;Dtn)bj)LjcpTfGxl6WW6tWP-0cb{$AA-yD$@ik{!o?j=xd#d6riX@eDWn zA)ucy1_v;-T_bIQqyJg4mSBaz(Zle!l1(OU{=d*De?6i*S5x3@zGToZz72P6*gszf zz`*5K(09cUbv>%0^7k-zW(@XIv2qYC#fqMwageX23c-7NB<`|2fDDI`QQU#DX|oY8 zsL?DJ=iY|a;S|yQKeXNDUzFb$FML9}Q(`cw zDQTn?BqRk1DJkXVJ~+;ka~^!JnIHec`}Nst*w@-?eUx2)hSoKdDocp`SGPh$dl2ex zaE52#%l&Nz{+6K?l@@j?P_=HMr0A|nGTD2gt2>p#Q4!2Df5+1M76>BD@STY5^5M(> z`wt!E|Mtv;%bV2^#&A8}(CfKTdhS|N!(tvsTdY(*)iO&Z#ahf(5AhRxeN%u8oLPO@ zuUqf6{V~YV4ELE#!Jziy2rPK~Kp@XxHsB&=82M?qP6nY~f-|^-p`KK&YxS?m2WGtj z3**@bw%Gf0sS+IWKLw11*fMS?;he=B00Vj+Qy7e)TJKs>xrXeiCb!i* zK|HsllDTEV8!Mv;0p_oA_sgX*0Wxft()7+u{;>H&c%wGJF9}VRSZ{C2N;_83f&F2t^Z4dgMg5;`_3Ebw6~)h)S<=kd)lmQ()40ihmvij z7{UzPGHC!9co^$KVGI(6*?cA=AE8`bW_ups&^`T9S+yZK{O0v*i}&A(oGJojU_H9q zV=7Xd-AhVG!K&x}qx;&}TK_0>$Pu5yGmWyX9ON_H(t}X1z!^Nj(C-zr+|P>|JZ6H` z8h4c?z){L2OOoWwMHYjsx7^LcbFUb(DiFV6jj$U7z~FoM;olx54CT#~dnw_`Y5bPu z+f1dUyCI>@VkcPnX6fh6e+UwO0%Q<4__5xGYJU2P?L>F)jmjHs@zIH|ghV_hyncf( zxSHQ1pMk>%-cFm z2EK&7ljEr;LA&@j`LyQbfMKG?&g&{x& zTBXD+}$93+>-*&Ob!6*nHN`-wg02uJ=_rJjoCDp->B8MR3 zFG@&DJx^6>R*WYAbBnV`HBdqI6`$=dJk-G9eD4 z02yYPP;#KZUyjFJoQYXJ?v$po|IIo!lB^O3-oP37PJ;Z8ph6F}A=KaD48C9}M>mI9|-BEgb{$mc-+~ux_m_Wyu zrpetrS7~^^qlYkqYy3|D4Eh}{|E7F)`CY>q7894}bo0aadbUgwuUDy2;G*%y6@>DBpE0(|Qon092ryLBGtC#0+2(BQXK}`Zey$NUV2Sc$3 zXgiAB_I~SIhne1_Yz>$4gzi$*`;KxiuE!qd$x&W0#Haj0n4xlkz4^bF=)+ZV4p`5=ezQcX&)e;LDv>S{R7Sr0ESxLAhN_u7Q1*u-~G8m;KvKv<@39c<UqWwV<4p(33*+K?S3Ylgx;ZAK(-(|uZ;36Gd#Fq z@a9&CzY4(GfETB!@^oDX^~saik1duWR09LjmO-Yc6<}Qduy<+h6v$^Vxtwdb1!o8Z zL({qI{1}C}bGdEhL+{nnynYxddL%D9SJK?L7ZuIYy>P|gGKcv0hSHQw01TlWPyg*v z@*7Z0uG_IvAc_y6)89HmedXPCCqKjdROfv2LZhP80U(33{K2(ApA}Bbfub3O8!mH? z3ec{*wPVI^)5y&x+w~nGpTX)KgnAp!0KVKRHeCJQdCbY>CjLfTVU^hvOY}BO%n4To zMv`DOsP)_aD+X6QNrVq2yYoo^42ogLRIoHaCyVK#zl7iRRCrR*rW>tr%A;DX_AwA$ zubHBobKwWjR$_jLjE3#Y>rs?~1h<>0!sbcmv)#D}moa{k?R<}L!}UQvgTn@ddI!$% z{PJ6LgP-t=Z%nqotsg|0@0A#bMk+GB-VHBy`NSo8*mY>^INfIC(ARmDU(gEJV@D ze_kH9?y3vSlAV@5u()DKvTj0{!TzfP00yf=IZ7Bq$HlTN?ISMtF6Gkq!fYqDy17x@!nv3&1d{?XNdy!_4mweaglaI-%f$#ZP#dx7gK~ry#p9WtU z2=z}mLl7AHcI{it6D!`63=Mw2N4GV}p_caF-q#l0F~lmfTgKr&ykdwlMSRLSVqe|5`b4pPPAj6Hmnoy5}pY1yY zv0T0Swad?b#l5LXn{Ai@J*^fMvqk>%bRo#)x9B}MLogWHDKfs2|9-=0-q@_z{n1Be zNk-{<0&S}wZNoe+vlM7cR}4m}_z0(gd8P#bL+zIidl-Y5R&s7Uk5%?}ajs|57ol|M z2M+w-XcFH<6FomT>gN;y$bc0o=-&K-09DQm)h&{2KpJIW(%@NY&i(j5eTf26gUD~5 z6pF})Q18PTLcq{jIlHfU+RhpDvGbGBzREEy@*J-tQx9;yy19dhYBt^erlImR!VDiR zj{q<%m%mtoF-Q;WMOcdIw;PauDQzLZr9rE6pCq|Q%cl~q*EQLcYYC8nkT~u&rfSfs zec+8$s)dYe9l`=H_#0e=KQNrH;_NUUApcN`zuZ)R0A~mVLqCqy_v2$P?lH)OsY=^- z)1a=3Hs7|yNolGRjZnGwNA-#!)e`ZUx0#1rt^d75cfL*eHfd}8Vn<*sMeVW{WH@^{@2Afg~`CZ1=$*t}v0h_=i;By3dCn7c0);KQ*7)S)I%_FONqD))($vPy%G=A=K14 z3Xczu_F?t&q(pJLBYeBDWS8Tm(H~zH?eBzG$Y;nFhEN~D8N$KPqsg;3fK03HS6sM$k1Y`WY|x<=!5k@SdeP-`etZuJegZ#bdc5gpK zI1Nf;vj7-uSE9mU4A81Jo*-JQ4{!Sx-;~7QqK8KQEPZ=u;7VxiAz!b|`UxPz8s!@Q zWJq-U_SzTul+kBYQ)e-`!80oC@xtT#hr_XC$Y&_K{OofKXNUwt8^Tn~NPfJ1Vp9l` zsaRrruaDhThPCEu!81C+w_lNSaFvGGO~fb2`~XwF`|q{E@7P!s#*kxXxH{CfccZy` zRxa-_pIW;;}ce7 zX8qQTN*x8$uli47rspM~zD~j@p(!?!{#R+RTa8DUVd!TB00tM8DREdDaEu`okzP+l zOFE^V)t*^EulI(9wH(~0bLj{ue?qdB50IheX6tngCGp~2ZD*{70&It0Qi zw}trmBNUMT%tWX|3PODbXNbAH%<%n2z4Eo8mZ^A#7sVV;-YSTdNRmXljUb$OG!dT$ z)>yBBiZBC7T?YULy=dWC7{fCO^9L^96hI(YVTN8afMm5}yG> zV=cx!w0o@$$Y=Oe3!(lEXNUts4HOGzlfn{zo2-}`Erg-C(cj8yLXmbIpbE%gc~~)% zbH%V&CXX$#g{KG(5*gcck_-tzc^f|Bk6gsoilenf~{WEO=JED`44i1rY~Cp{=gaH!B7rS zS|w&QY|kmD3>^i?@Wxla;Awc7mdZ68M@kbv1=BdT z9AaVdB~dCzBgwI1dE}>I;WmW&0?v>Ch8Br=QSN5MQdmVAUFbgj8cEitr^cbvAsv4) zH2?W|{`D&c-DD4h8FX<=05GVz$7{kEme3lK=Kf62O1&e--H9*B~EwIxFME9xfg*lM^OlD4WLp4vSg)Xmcine1pYD&=68va}o3SB;V(oo_7re`3#415D*%i z;ls!MZnhBZp(j1B~vI?r=2;jitwu8|@|*7%FO^{vU=q)U_7~Gl)#;0bsBd zZ*zqmN@DGHx?J*l@fz34demN6(xNpmCe8^Ojg}7{in&KGJORkiOHG}DR)p%R>rC_Q zms!X$x6HCA8JV=y%B$)8C_>D)$Y=OX0|BAK8Ir-!Ii`K1vba?~%7MG0k4>foX-GiMq7AR|NL`-M?xS5s5H^?pPuK27yqXbr=KV=5|15iP+Oetx?~_rXLOt71MbZ zFRQkO7*Ei8EzaKp$nde>{k#gw@58)lD?s$2W+V8X|lq!z8 z>+6dEvJqPcD8bou+&x!bw*?o;9BsgITtd&N^D& z!3(U|u;A@-MOPF3HadU|uIfgg8o#wVmC$f>8Pi>CEUQy)eJieTA!;*jdg~ed5cv$G zvk(v_oFNqq-E8psVeS3v z%w0Ykb%van2AD&t=oqR2C(Ea?WAjDGXP~BofUw{UuP%4&8F)GjfL=*e-74=J1+98p zC1OA+Udb+xtqS$#Eh)}lF;s3q&;S6bD=-mO!N@F|1F~j*M8C^RS7Wr;gfo+B=?U2Zf;PJH4mMaG1HEM(zin!|l zFt8MoHNzONv%jEk(nx%pt#*9k>4w?rNhhqw`^*R8mbK<*ovR3R8!=k+=wcZmtHXBe z`+}3sibH%YOD5~-L=C;IX%^MpLVn~kuoXZ+IB7KM0l=^=etrwaFsNcre^it=7XR)#14hI<>IW5{ zzV5QcEr@QiC{cg)jR2Siyb8;N`wWxPqUrt3Xs?!3f29qIUUaAr~j%F3p+bR}5yz7?mD*`@?@P z(R?Sr6JZPvx+-7(l-d`6nrd&dzt{5mP1j8toX_~2vv0h@Owicx0Azq#5-z=UVf`c# zD13HJ%Id|&^oXPTVN#e6TYBjJC$=4W#u zO`^&V~F|4+-t z^Nxm3Y|GE#BJe>lb|*jvmD#&#D$uG2xZex83$LLXDOxyut6L`dvZ$rXq|{oChkOQc zcL)d{&X9Ha_3h^fUu?j}!svt+QyHd>KFR?IW5j+Z602YOy zV2GQmU4t=j-|P%32jS`D(QAWl3CXbM`EY4vGU}_Z3M}T6&f*gQWDuX-zw2n)7)%h} z8SLW6MdH`<{$LZM4xY%r9%`y*cJQU9@yL?zzd`785V zY1eJ`Q?J!I7_5luYC8Sx=#CL;M7TD*l$i#=5Ov|53S)Q>)AMnvXnSl@BCs^3=%L^} zf{8y`zqcapma}%v#AvAjWH9jwt6TnLZS}ME59p2eu8U#c!q3e6DxIc+e1*CWlv>D7 zgUU4sh!D;I1w#eqf+T1=spn9>nRFAIeDoszIsX+cYb#!DLFKDY>q+rd8ZuYL5N1eE zB<=X`wZZX?;R1}|c%E?^+OOX|-WkKbPOEo*VBGEY?m;uTc#kNK}!V!B7!sIfT7*^v(H$QUrCCJt-SPn z4)V=7Rs@Ys_xaG?lBjuEu+@IWkhfxhFvI$)G5`jmO0H=bLxdRRh96%H_NnSeT4<$S z{UNc9*izuhg)hyc&fD~X=>QobcA1_fgonHL-aRuexE`EjI7A*1pB{6Pze3Nxf*XMR zk%z*DFCideI72QNdUNaJ23x(gCs}SGdbVq!x!kkItPiqppQh+PaeKqgH+jY2u#|@| zL*TkmsK-PbjkT=q4htm^Ql&Gz~M81r8ri zeHVh0R7Z`s)EHAL9}t?gCG?24x%~WG%C(35G+2CtfJopBd0^;PL@xE)@~$A^Z6|*m zo5E?`skeE_Pz7uhaw1h1KlQ(h14=z{5oRzicn^T#+K>n-EDeDt!I*gSxBj$lzDj3l z#b41>hdxap@%JAs`7=IZya;%4z^jRo0Fn)%Pd6m0+^`nYqI81qxm07%FAi&oOFvVu zKt6*VCj>+aXUM;Ng1A1yM()wr(4^yi*TOn5dwG`jP5_5jN#7R=XEILpzpcd1+iwwO zh$A`&z`&Rh@Ds)`aJv#;SAQ@l@gYfU0kg{c-4oTPrWnP(>$esOiK_jo03J#)r4!?I zrzi2wLBcANGvBI36zV&14!jw5#yBsYM%UXTpTX4^0wRMm6kL|*m**1uov)Y{AK4sE zzyHI?&jcP<=vWYh+FBWRh2@-F9ZIj7Wf5k;eSW|5zn5sCTCsmKy2}gpwFXM`T$m^J zWycl27z@<$aDlVA*u9}Sj7jj3DMCzG-F10XsT?61O=)C-wbP*R=xI9Wph zreP!6G`i?7*G#r|deTuE-uRGk@UiLOo$PkmSTipGW2Y=2e4cgqZ=V#Wb0 z8WlzMdV9pZYjVhENWp=CZonCe!O#WQ7ucEGDmP}vtJDe$V}yF1Wz@8;6!=W}MN^|f znQ^Ze$|Vu+VI^lV1i%pC6h8`M;O*Vt`uRxiN&AY}gSI2Taym4{1pz&56Y$Zgvs!`5 zJAi3`Zby#33BAikG4Nu3d46*h=V&#Xwtjt-ivi>FXEl#xjjC)K+P zu7{IJ<%%gATQFNc7r;S8lG$As`w!Lpd0#+9MZ_#*+1W@OG8EeesXmwybyQYj>$IHY+8b zR|&EH9c%SUVIN@zj~*ES4DW(&3d0y=3$#!IMk^?Y?#q3OAXA`3k*2aB9bLGf>Qqr8 zkxc^n_Km{D!)ChfU9FXF726n7;$!W1c=RFkXps8BV*iPQ22A8LG?hU>v~Y$BFf@8I zC`jqk_?s}1e9!FrkOE^q36GyP4wM!y7&1+&C6 z`)%L7zrU2Me;~fUfmOO00K-LrR{z3$l|%jaqTBDB7U47m5gY+vFxEO^fu$jB zuIL@9a{W&-PopJeSyRXx7ZdXIkBRxAZqO}Ob}n*&X^560IP@SGk^8p(`_*a((U*JhBFT{C_xS9r?}}m;k1fB3vqORpBg^p znqe@r{GfexD1}HNe$g#BcdzHam*|Y)GYl956mL|nYCaxsq-tQ&*_A_cZTf`#ByY8M1_ z6V6Zvh7R!tA1!_~u70=5a$)tst0#F5o8vhTzU!XG^F?uU;e;y&gP90~YlDa1A^?Uq zMO{M}L)wmA`h-FD1mz*S`M5=wn6CNBz`C+B@Ap@cOEefC5&<%_uW|?0D;d0~g4k&< z;%Au!T94b4)0yAdVL>sjtIw@QKEpO61jGzysK1;b!^IUm#LPW-!-FAuDC2EXrfqlU z4~rH(Z^-01cp>iZRAQZ{3-)qDAS^CS+Kf?w?$Axc=~4SQS!0hZ;|hs{oEN*`>JJk&TRX8kk4=! z00G^CGc%lP$tE%SW> zfyBkdbGAR`ORk_O#$}*5y(t8KtcrYw^UL=QEO3TKFqH9AuNj^dt93=;H}TT~uP4}S z4Aq&gLt#y``G%uTDkWD8HhzfzVEt*72!LT<&fNgUptdc@d}k@BS9a^Io6Gir>{J7n z?-sk)z+)7D1Jt0GKpBQ2VuPIe|73MeJ!hshyrGMV@k-~D>)MXA%H9v8Gl*Oh zfq+=y3~#|uiK$QT4U^Cw)9$S_+NA~1r{ZSkHL^>f5XLCh4-Xb#T``oEBmNPT!+a0` zgVI!2JB%T3>(BXA>X;d;sh28)(_0!`Lp($sH?F7e?j%P#c+O30reBl7=0x?+PfG+p+vGLFRrVKI#;oRILS{!HJW z2-q>nhmN>@INtMgf{M{!F_h$fMYuNfIAHhw_u8O+L*y97(D~A`|ECKWn;`TthMATU z{xKD%gEfBPhAAGYDpz2;FdPIvcQTawMz^-;v5JY0 z{4|iBLqNCT49%B!N+qlpcIsA-pPR_Px4wt&F*qiHzIe2Y(HMwJ@+dVWPa zvZS6ZOo-qJwX#Le%FK&f?*qutYK;G=f87_-?(|Nj#gq%Dv1_I1Yf7MHmCLqgbhuOhe8WJ=R_ThtK4unS zhHuSp0WjpLlRLo}tnBD4(8}dNVIcFtsIcSoO&hF>rNr568x}>=-;=Iq02v&2LGpQY z6?ScUPEOIiD*o!IKYnaPr9V5;{9fdk0}i4;2{BI?Am^1=Q)YcEEe6k!Iel>-0_S);iYFoxBee#=%g6c2AeW#=x8 zBD>sKP~I{byha|I4ih+(whguh-@VM`cgb8h}`sxIG_^gx>1v8U$c!p%QlnNY6 zA)n!1Bm{I9&d>&ip7+#jlKR-cjuO7}lKf_flSzPih@7)@^U%z?jaSR{qpLKSzBxmf zA%Wsv-+wRB2FB!mFop;IO1Dy_Pte&=l5VC^r9smP+auK|hxRhe!6oKP%58X)tg_*jP^u!nHso;4t1AQ_OA5wP}QD5Z!@o5G02CHhpn7A-$;H3U>ZW+ zh4(Fc1@E`6gN-NW?Y?|wGhmpg*!4I6xe3AgQyhi-G|09>K=Efa1$HReSVX$Y-i4ZY zahhy!-Zq?J7OWY25FX$5ExuY{c?5R|AcJDc!rB}uUF&+vMDv5U26A5Cf|uyMN5)C- zEU=zmqqRal!=uX*%?)ShxV+53p=b{cmYNSHzu;u_yd^R% z5vb#zu`f}vh-M)8B=}y+&J3DwXkGS=@H=n+P6;T$C`XtfS8x~r!wbB)f9+z?t%T9sMa!)pR za3FiRjU%=NE{~C)2K!+Mh#$_-1BQ~Q>1~<#Y)LfuogNR>{o;CWj9&gFi}^)7FPMCm zPl@R&4NlJyZ>)FC#~t|ZwV}cb?=vh7X-^piYmRnvO!u?|?~p|fB!;@Yutn4GE5Qi> zS^v&W0mu-ki+kf@Ir2C@yKaqf8ogAReln{}16^q2x#OwN*`g-$8J>zlK==e2L1d<7^7}E2t5l%zdby)xm;R*x)8f4V7 zsYH5o>0Zxu;XdO_T(XA$sGyfKQY}4!o$wny>Bl@+PN8 zetaYO_+T_RDFT}g`44hMe2O6;0XRc17&^IOKp4nD?PO28LsH&+UOPw6+un~l2>N70 zuKcZlq4kO(H!2Ka2HnKx02q>1G5G&Zmm<@0^cD z+Ca&cK&J%sKjC7*-4_(fpHs~C{GPflU@f7@g}cVHE{r2&UOJDB{4_wQARs|FL*Hd> zps6agjPK?q;UbMKA^N#5G-t@bJ+7dgo5K^l>d`oN#qe%J1z`pk@>T#0b1{AYYJ+QY zcJw*hE{nZziGN_Xl`fl%mCyo5$zapx;fVa#BtR#~XjEhwT$g)jiOwbvU?hU+H(DZB zpo9{kj~A9~=P%fAihPEM2na|B&d?8rCK2H%6zUhIewi&tjblB-;c8=#t>GNl`9Ll+ zrbkiww}&-%I~QSwlgwiP47FJpGO*g9BD7o7S(k3A*TLM_nGM1?=XskXmvK6C7`!BU ztKFOi;GxuEvu%AGJcgx9JuWXbD%CmsB(l50gTThK=7$O`86olq`G~}yLO{ZBh5<12 zY4sbbn4hSf5ibbO+zyW_^*&5bwwf7G1oykIWU6KT?aX*Pi1_-weNMi?|6Za)X;wbK z7@o3g`bMycNgfMTlgGt_$gJj%yOO|7nR4vAe>PA}G66DJb_qoAC6aWcl|pVX|9P>&VEVg9 zomCaN=#7*G3|EKJQxU|w_Dp-60Wc79kaoft+D!Ta%yczIS_*sIlpb^5S2Zzx!xXzW zMQ@~W|6A1o(8-g(?`yQ>_-O~<6>^Um3p;)!aG_(XSFSbuA$**MumSZq@(-o#c?d`p z&M*Xqxx#ey^RA;xnyBk-P=9k|bg3clH@bV^(@z|8nRT0hor!;dKm>)O@$Lo`jZw zMN_Dlp1FE&Wm4%G33IwG`xhtVGrZP-fW+Vo!s8?VFDz3Bt7@o^TBS!#5c$JXjjaei8Gx>XUI9QxsL@7_=DPHuS8e zoq8&f*u<~gY10IBD)EiBK9X?fQ#LLiwaPhds{#FS9Fwo8Ium1yyAd3VhW~>@sk|Ek z5{EO4fT8|#Tm$uGYIh!uQ$2s|ANi1TY{-$lcW9YdqUq7RbTHLb8Z7Lm5N6P6Wg7bL zwZZ*6z7mW3X&~=;(1EUi|2g(t+24!`Xo(i~P%TMqZ=&y% z6Fsuu+U^QXTlvltTFr@Bd~fhZA)_Sn(@=lerz8Pq_ymU5{!~aE+E{te(3KxLbl>E+#x% z%6g=nMsWmv7{Hy5U9ND=9UmaWq(D<>o?dBsFaKwPm?97>6*`sOp-IeZezQ^e&mhPBYn4U-8B(^b zSl4JHf96y0TU>~)J&3+Bj~{_`vzvm(XIHWpiv#%#If`Fvq43n3a8LU>X)N|J%7@8D1!y9nRgx_Ly=M{;nL&ZUIYP7Y$z{>$LBu(80L#*Mq6?Z zWNSExe~NsDjmvg1SvbQq82Vzk{F#hQj)=|}I?8R(Cnj%`u^YA-5kmWWZaj4jX`inc zys8nOJo!ixb>zR-1_Js}6Bt8C`=*G70%6F5j9Syw6?L^AB`;0yN8k|_a7L3#wMtn5 zWJsfJ`ta4=g735jH6|sGba&U&vVCb$3dv&+; zUaQsvu5I^lVxjwL!k;+~{B=+Qz64hRBH8k>-pi%CLaIk{GU*(JfO{!ij2b?O*W7W$Hy;T(sos|Mh}s`6q_-o z=Rq5IotE(d`Gb5!PC_6cc{sxtF!Um$PEY<=(|W>97ee-wVx=urKg4#gCx!2>AC>2Q z7qTmc*q4Yie7WNdfMIqRwFkz~l#63ZJD8BLNdAc?jpgCk2iAzY+z$qs__&`@8l5>m z1(*i183!t!u4T0NmD{&$Ncxqz;(QoQ9`=>&w{R!UXTIA(dKyGgFNZZKz!_%1&@&Al zYL7WeRLKh74q=;~_>r`GnQLx$FjW4~od|8P$zL(pXz(MPhB=Np01O}SDMDZjua-YX zwg_%}G4TuFce{-ml1Qx1^%{73NLrpPk0;bU1jt~@zVp69`qx~4CWFpbs^o1lk#zsh zbc`m+cf}ZJr1R^M&ww2a0V%>6X2DQ$B8Iho21bdJ@>&&+)M_6LYwm_KfrywWYixpg z*S?+q!%#<5!h$e^1^-U~3_Ne2n8FyodoBi*1yn~r`P{s&-O^6`Hab7c*&`{k@H>W6 zOXwKTw{MA3G3U=Oq`&^k3)VgdC19O-7v^v0f$y~On7r~--Hk^+12F~!qy%U93Wi!V z>%1fKVZ%gQ(dVJUEX@%PS=}!mL7(3?*q$b(`}Ox~4=S^RFoTWE-B16$L}T49FM}~S zs-{{xf9d2@J=S|i6i{K$?qS{x%} zlx>{bDy4ChKKR;=8UJ6%XSf~)0V%^7=D^Tv+_go#-o2z}pS8?%EB)`kET%SP%c>F~ zGkr|%Q^`qqbtsvR>>rDBkQ$SmnGq!iAYAx~^=r2bes=yiM z!O-HnHtHZs_o*ZP$kERStx@ZGZrF`nj5AbnlxdGz$r!H~iaB@@X87e>0D!@o)iN5E z2BN4cCe6yOhM85zlh3^lZU&j;^;Yk@lLiTMHeIw6g8-&s{4iI1LgUl3PsKs$3)_T@ z>IyMg-HO+v{=9v6fF`zJfqVv*Xb9*LoMGYeTeSH%bh*htnRo@BY$Nk7x`K%&q)p9l zk9f5rl5aH7{(To+YD9oALs0G_00yhEk1H?+&BCKbqhnH2LbQk2tm%`3?|50Epl^l! zy2g>%x+r>6==b9^&A2ezNUVHy6WS``I?UWyLA~t5!St!5nqs4vXGjI|^K&o(t zMKH97>ru5f-F)xaE;)P1WI$oYBm4Ag*UF0`j*3XaEPo7MrNLDw2w{e#5!%uJUK{9N z(X_%CFquJd!pp-XBeeI_$_~Fr72KM!)qW(glkGpRqBdKoC3{q^*Q}2L5CSNDa>L4Gg^}sWlzTF)=LMs<~b`xGJM?qPj*q@OA2h z$b7r>)_oP0WuPT`^HiOHBjB^MnzyB7!{9(o5mfipaix^cNq~eR8}DKb@)^WH5Rf{Y zVF?V4pftL$5#{4$HVBI2+;1eHzUjp`P)o%iru|YE#4LGs#Skz48({`1sT2SVeMY~$ zU<@q6T7-0uyi=(@f@;Q^;&=%MlIuk4V{PP)-P{irkGg?HDCU2 zy{mCYx^Uu1;CI(hUo)icp8IiY&E8Vzlbk|ep)EU-`M)adtLBn z-R)ua`P2f%?@9hGvT^L_8)(UNMtf`Ztg5P@?D%^U(WK@v&?y0z*J+bH*se!oJq+EC zl9%llf+ zqN4owSu}bRMR%tFrh$_Co{U^+R@azg0~T?S_wu>^Cw#oV(S$yaSmj(TTI9b36*Uxt zfVANZYnPj@639r7v~NfX%so@*I>^7*s=`K9KnOEjK*9hp z7+QWKgE6oT%QJp=#Z+^l*zutY#!FB>k7gM4Ho)gvG^{T@Z3Ft+2RywsHWzlbLdZ+qb#z7}~7sP&ObDWqPtDfib*4{XIj`LuL>&`fL2a_ubS(r@x&UVGIHYGl0}k z#{YY5AX91nx2U*NBK6T>>pi}XhJxjJBR^iwhrxlZ_KKT3dmhX|^#?$onUHq58Ghn6 zHQ_W&y!d!JC2eNTECqU7YqftsRLw20;}3%{ zv7c67@BB7m$8q7St$HA?%Ec7}lT;S8H#DCj|R&4Qsgu38KlE>5zg3^m5W8?^J*@b-)ACGNR*Pp=pn23HVH zgT0710EVJ5I?g(prLHS~&!u9v-+w;4Y2s7BW)B#{fkjSWqF<2yupm7eklrNE(h7Es| zdz((uhWjIoK?egz+t|>98w`-)m5vhz1^T;Lw2)s;Ns3-S1R3cK%cbHJu_fcSayK77 zKt4nG<@0nyIKvhg8ipUnXD&l(B>jU;%*^S|!^7`^zV_+oRkG#mj-4a|e-EY4u4@Q0 z{F2@Sz+k%Ms{><*#d3A_R&yP_sJp|=*w_rQzkYXTiUlHd$Qk~U`oJU#AVXQ@#K~EL z*DrTRCDYW2-{ClpMmeIZDS6e$`N2AoddT09D;iG^0U5y=w!u(rVIS>kJ1slObHQ0B zd7@N8P95_6QNuSZ4vK#gChEMe4khD0C4?C$Cpahmdx^%AkQ#{%sYs1(1OaP2pG-O3d=c`_4gMK$=)tqKB5&38VPxY;o+I zkcK+))9~`LmDm{0umgs^+QDS?<+T#gXgBGybG^sU57l+~iou1h z8exVW2YUbvbob_IVGO@2{r3o0ewX;xRi=#$+_%j?7tmm&#Uq;E%J?Rx3X%lK0P2v> zvPU0()WDB%1i49^IKwU&TF;4!1^(0=?PnS( zz`<#OxApywraj&}f0OVoEBz3;y(@+m@-c)NaPf-(FhE9m>R=4)pE{krWz%Hoo01<| zq?Fwlr+LqM|c?i&j@oWJ>_uSK@Gnlh>Nm zQU8DNgSBuH0y2d&`~*X}PeWLzxGVHNw{DDuSy_fv)LOlMvqXu@{!Z9}mkQc-#b8T` z_^^hB>SX{78nlNwFb2ld69WCpzGXX2ruGjiYj2MlI9aE|B$PU_>!Ns?53&I=3>#}5 zvK{fECu_w0e)+W+5AzG(?|p$&@zHJpf`r8e!zN(yJS)Usq zRwzC(+XBA_hUS7d!;~Di8 zgOw%XkFFH1n*d;_JgWM)6SPM?K2_LEE7d#CK7id;!EIl?NKH-m1{0OL4(d=~lmS47 zyJ3v`}P)#RU%A)lf3^6Q%goZ$cr9Zm3e0-dv;?`hQe8rHwl8$g1=ElA?=A8l%eWN3AL& zwe`O&!yWmfJ_+}Yp+s(Wv3F+MuXBz<0W!4JU1P6H>h8B-H5F(0ja#QrJTA5#HC*@6 zGp-=#A;=Q>3|$-$&|^5m;pH=v=})D1$JS-bSKD*0$(tLd2J?;JFIM$sKU2`2i4y+1 zJ>6?L4q*n|v?%}#j;Sl+Fa{OyQ&tQ}|L6A+hnzHJi?LsA{3*5Ww!K#3(?~D;gUShz z;YQT1cE_>fP4GUZuSiORAx)Q&g0yctR=KCJ>q9dxoMS{d@wFm4P1S-}~8UA~K!=r^%?mX$O9)FAXHuYx^DLSZVIzT?$Oru5gK z6zqnpLuu238exVzBI*DbhTTQ~U3BZZ5?8Kr{W{jP@@|!7u`UQ+sK`OVuTj_S*B=j( zpa420fXp+Wrq&4hm@^<&xSwmCP|lODx3Tqh;%ulUrWmKjH1Zi{enCLiaE4gK^~Tdx%F=z zy|ub*?TT28%Flm)5v-^WR_4uwu2va_J-KBB^#2C0!^c@}!x|3cUz3PI)Re^P{yaEO zCUoCVOAe4hyANiO&#;sT0olMAPQXyxH}_JeMe-}q-Rl#WDpn}w31if=vq7| zyNMcf#b7y1hcH9!X&(TF+K!>`t;mUqN0ihtGaNzPpSHom-iK}7~Ulz{_oqj6|Cw1UK>1>ZZW|a z;@*+d5TLB*acME)|7bTNbZLEEuDUWqT8@sLdWtPA4Upj`?Wyr+XP44G!(MLw=akB5 zropN-($>8TnZG)xw0%R6pN74D2*?)Ba0Z5UVa{wEpE#5a+Bo2BG29AOE6B({Q?xB> znq8*T?wwq^VlW>&K{yR%)6xJK#FBM3VGLoK+<#^m1a2AxAHV&XNGR!0ms&W|-$s0W z?B;#{i87!!tWcwySQQ++PaO-GR)wjS`MscJ8BZ7bPz(w7TJ3z8D;P6O=i|{?46OM)Uo&8qwG!gmaIa^-r?)^)p?(vd!6(7 z8}7Hq^?Y5|>$;xLAr}MvBE43{q-tG0PO>?HxXaLBdifOGE!g)9DPbJ0pq1|1r$F%#K zgd-kuy#X<3TaMBV$Y;2{1_9aq$KZtmhBjg{pb=vIhN>Ixt5M?e|A|N~5Af+slAn5( z-u~{@^4~{S1!xxtr{M(46##>o>Bkco1Eobn_oFWMf?fC`4z zD%N8_+hT)CvVPrb%f&otU?0OT@}};~E}FSZ-CuNdv{!N6X%%6H5T-H!4A(zL#ljda zt7SkoUUh+{vSYVegtC&EYDm!SBa4qoL=Uh1=yL?xUF=J^PB@jAJY(~1=BJfjT8)pT zPPs|`?4E#SY>vJMc%mVnfsqRWa)2|ST{efNg0grXEhy(~oo3Ki7E+QQz83GbJ`H`u zM5L?jfa7|#DAnd8extiqWeWg9b9Ur^2i>lvL9OyEwegy3VFI#6G@Wa{uRet?84z70 zt_6@sR$kt->wU5^+oAU=FR;SAvUlXpFp)GUKFpbTD@Ec=Y$Q%Lo}EOKNp>MNb$tj= z5?5wt$m^U&2pY7N^IrLM7<S&EtMFWRhi+P3^(L6u#ZDPj&KHa zFqCMS>;861k`Wzc+YEoOn0rPk#hlIsv6L_ zyCB1LBg7U*BU7l@KN)0%{SZ=TyWuK_eb@S=_TjAuBVj-r`8?UhY)t9w>k?Ox=AiKi z-p7`)KY8(WN9$Q|h4D4+BILI`6n^9d0Xe}LFu+h27p2O0VgJ1lm9w$Hyj~`~e$gaD zm8ErC{oG{-iJGh{27i%Cgcl|J8Y=({6Qhg&?HkCh6Muz{mqO2pBRa1Jr z>DU?YKBI3!RV@aXhDX)o0YMj3Mihz{!4C!q)v;nLYka7AXdvC9Mb4O*7RXP7C@lo^ z63%e#a?%z0n%FHDk6RdiJI-1ADoi-6jIT<;QKV>w)mCIOT7Ns%t4Ap!%)ow>1%M$a z%TNJU8zg-V6CccGDmPDX=H04JvsPIM=E>sy6jdN8F(3sF2?of(_(|6R1B)@r7aH0K|s!M2F%L~GA$3PIya>;QC}xaXYZ0()DyZh z7x^uZqCADLqfjY{UZo)@M;2j*Bat5f7$8+?;V_2Q>lb4+3d1+>MX~u)HtGJ{W@Qc- zu`tKX(OK;ko-zIgkb(GafJfI++-U?Uh+2FAGBzW@I7f>fsULbr=|kPe=nu$eP;!KT zT;L4X!B8vT0v$b$&2RQ&7Vj_6jc$Ub-lm#`*?lhWV@P7<-`%}paCW+fFoR_z?exFb z21nDNZWsgmSMo}#!?J$-AGxOd(v`f6%%MM=$wqyTzEsFd73(qqWZ>8|P8Scx5E~lA ze()oD|Goc{l<0f`C${DGB_6WVJ22n=e})QbuSSF!{1*)XFo>QLM!^`U1NB#x`7t0qcW#O2#01&9 zg!~d3D0QU(l9nOGrIjHzk*sgs{>K#ij`h4-{ z(I;ATJsrdMf_(bMCiQait>&*7>@$rJW~j`Z0>I!0&Xd!2>X~knG(d(odAyHx8>7G#sjAQJHBbl$rXTd-9!JX-lhTA1FFPQA zaDcGw<-2GPI0G&idMrlcS5Z$>^kLfKyM?^L6n?8=Yv*zRr-k<_x@OW8p z&*OBteq=E+XLQ>5wrYP-PFRtd%cy)l{ku@SZRDrH`SR`CD>wrl7~0wK^fYB)PkT5d zl@$Fsajc#&drHx>wSfe_H+CxN?0=siYQFGBnBiT>a{vszd4B)B_6aB^uPk&MpQ_Dh z@mB3!=dL;S=M$1WiE4Uj^Y|-$7|@;>Md!35@1R(x{Dz@rI?tMD56c8|cvpHSFn%|o z-P_#0j(i3$R|v=x&VUbwj+84h)n0hA44nyc$?@M|JX(LDC@@pLw4ctM@mXy;2=1sKCmaL4rQ$n4tQ zSJlXpiCm1T;D-)W94sm7=;@AB5d1WNi_#6slUbo248cvM2qQVDKsSxC%z)canaK+M zk0k|BL2l$TgpWc%-f#v2Ff`^-&=H$*efrP-m1omG?A@?HHddkO zWUzZGPIN5PMI;0zFXbB;AA5ao)G<}LMD*9EX8Dj+ALO^g6^;vnfPCN#H!u4st#jzP zVw`)Y(2!6_^UPQ!kf#VrV%S$j{C`7q_G17HY*;9{Fb2}VHtUAu z{%~ShRxT8@;fwJPsYiJpzP1(diqh9|qAdY3h%2n!mb{lOqM{8%LI7%X!HqrZ?|%5*Kj* zGQ5>&vzl8V#CQFnO_NQt##_z%IrpByE$eoT>+_}!YskM!ES!4z_YDkZAOb_bxuBBN zMP&|Nzsp%8laSTQnQR^QGnsp;O#KywF@E*mwpKr@(GX@R{n-wHfv{O*9L8|Rr1^`i zq(1F*`CD=Hbe{Kwe$=;q=^AKg^;G*oes|ylWDrBK_*vFi?JbpA_Su3+naA%}=0aSV ztlE^=M8;smtHV?coWh4lmyKY^96*9Md@`?Iz zK>6>Zt4}S$2s5a}V9fq|Z7?w7s)aEW(eSSRg#IZAf5@Cd;R#JqI@^&bw{z)jWcQD& z>Z1AykYQ|@$Q1`-)k93sy;hfp{n9L0k7LyWB+_P+TZFv{`X3x-lwLM#fWR3@z|fjx zEWU0M0D-4wqhsKTp)>)IF@F-pUhWL^}OJ<6@Uyie7k#o2WRio#G?~DsO70Y(y#kG z9k6|^@=<8jM$dI0`Dv)dfq?ws45VOa*2<`6MUb9(!%b(yJ}r5McbVFt>1${!Z1NX7 z4&?@||6igj#1wQ8W+*!I1;Bv)`SmD_;d`9Wm+up~YhijhvBCtNr+X9JV;ZaG&Eg

    }-SHzqNg01YAcIHjebySIa*z?hwaKM|VJF9xPy7)J9W^Tn|c!Sb{{;f_OYX4)wn*zsPiOTN zSHOJk?)hhF$9{keyf$V~c5Q1_{rKXVmD}L-nuPY2jEJZ5p&eDjlfhA|$Y+?#f`CHc z40piL0+53=R3%B+t(nV_Gt9;PbJje79knNoqCTgLQN=j7-nNDIWNLs6css9S!nKQ=lP@N# zO6I;r<>+L8d(=kLm7$MM?DCL(3i%9&vk*`?oPiPy{nEo}n&$Di$f&db?GWBayq{^r zieoV^ytwNKTt(2?{*K>^%$Yzq4FpSe02pc+q77lS0ji5i)h;uxiq-Xlo?y-EQ5TO=0FdNC;0I_)yoJ-_uoxTkdS z0RoDEGf-XjVO?&dyq2BlHs#ll9OtCmW!PN3TkYlPa`?<=t>>~|@l_gpI)5X~khho* zfFblk@+FL+UMF%DT^>;5sw@(xrhy<%`V_du8dbL|%Z23&QmbQpt|48)m+bicWQ`x=$X-i;6o zkCPimkH@clXe2fMa{q-rK!z>j_i~Z5wb!_V!)6BmoJt0heNoXY^lBls`r!4>KEoUN z3Sp+mNk^o-a?t(@t~fm&d#WkYQAM#7)kh z;>KVvUDJce-%E6}Y+Ylx&0a297G=n1xHSU-MZ+0rz|cpxKN$9meKu04w@LhH z>{cRn(S6-epS<&hD(PX+YrF9)2D2N8zxFx1X%2v4D9-G^uEb~WOrT5j2|q4~$Qjni zJlo!?ldbwoEj;D%RtagV=m4hSOCwdW)+u#On-uAg!EbJRuI4hyx*ZlDTq><4 zW$!cOUkMOlyS$kZ3umAMLqDQIZKPSKL-N8uFZpq>bk6=z1KU2vy5U&qo9n!gse8o` z+l2U|E1CeBg@3ON z4D|*MH>-J-r9&l*=bLa}?8mz*6K$x!SUR*{-1Ha3M*g5;5uRTVP#m0r9t<^isa&bz zksR5+<6l_gdA|7O4Kcdm^TT@cBO&v_!rinhh7Z<%5KaSbtpNZAC4CMhSQ^SGbvbEu z?8350GNr;<``F_43p}bFE(~|Qi(}2S=Yh6L2cL0@CLA5@CEzgN@i!<-Lf8EpaEosT zEWaaZKjXTkfc!;CxEKP8hchsMp_`Bo(-h;)HF&S0c3jTQ=vJCA=pz!muiaZBJ6(A$ zv~|UxNVK#- z-TDAsyxt=|qw9($$%z}(SyAPQcI$DqFC8I&|2M=S2W7L1|wWyufm zslm-qqi1X->nd`V(u-&FEX(v_+>4C$qbNZ44Ky@nIUjK*q#`MKHbw=W1cs4BXt(^V z=nI{Hle>KPnlJJho`^y~32+9+%NyN&HoCT9?&UlX78EuTq3YM`{>o!9zU!Z6MPIW;d9BKAzx=uZ9+cs8J=JE%y&*{3}uz}42+#_95ZCgIV3wJ0@#mJnv}_^t_n;i<+q3mC)i zrzP`s#cg;gEd+GBtBGeUhwpu|)MWZt0w1v~l-2<4ATv8=cE34_nXbae&V-gc%W+gl z0ZWg8?ejW4Ht8eZhEC)&=ng?ZiEswy%YI4?EF&8JnD#TWPJZaF_{u` zu%G=~2Y_klpy+*1eJAEnN!S9SQ?OG0RfRwFHe`iJhCWw-GD8LVSBXVTk|CgXaE1q9 z=-o}sn;rd`v8fzCrO?BfBuIN>I?kw}z3#Sd@;;ICe|OQ=LWu7hR-mH*7|#6fM8X&X z2m z06%Nrv77>_OVJf~oP-z*V7QwsJ|1;9{Lo;w0# z$dcn7Pj2~L?cj^MQSSCIdh+z1n|wQ2)SpC1l0?QJP={29S8D zd{+ZE?nmbn1>BOGCmzUW@VXpg{{hax28K4^EC-Eqx<7Iq`aCHZNX!gz-@%*@Q^z_N z!(N#Us2KUXZ-_&@9d7v9YXA&U&bc{a;2LtJQk1LHs? zwareb-Jbh6;wRAO>BM+A2Qgz1jW>E)`H|0%Mh*d` zz!|u~(13L5{Lw#EHudL8xGg;TB+*OxA6_xY9EMptqgjr!#$Bahwl@-ChLPDW01Wzx z^8YpRaguSAo9WH@gB^ZizT%OPs8E2(w7XJLV&fwOGPRTN5%Lsx+>@7 zS$6A9cU`((^MoC5=efJwdQzyR$Y;pifPhlr3=c0qSRK%$YR);oe4gP@L7km5eOzs? zcI&#ipcgs^`1xIb+5cy#An2b$n4u{Y>*v4M1}-b{|DLDQO1a!Qt2y)3OYu`U*L2Vz zd9*}(Vj#ZybuyfRyty9e2W#Aj-Ld%R{`c;UlWFNBO^s6Wl)2gr`cd?PboI?|Xb6zc zP}&RurNJ3^F1w56g3#|5mk@rU!BNa7oS;%nqN&d$oqc$gms|gCAshcH4JC`C2s8K# z$pT=ABlpLKElO@PAk*cW@h!z&?IIF}HO|-CUyp58c{haD7bZS(U?BjQhMRkIsTjBd zKHt^|6LY>Ay=hVv=UcM!@#}lpm)+(m^bYw9wTTc=I-G$Q4DF3^;B13^$)>}Jev3qMO7{;PzR}A0tDiCG} zt7!$mK!4rl8;pTAJ4OF6oc)A^?M21MJm8u4uD zHUFRv;t)#a~lDyy&|WqCn2Y?$)WjQtVa%!441Ckm0k3 z7(2e+D+>vgP;rW5qvbLx1BQ;~p;Di1t-NR7YI%{*FnIz2Wy2W+z)(`}FZvW^-yha} zJPgbISaSA_T;w6seIvZQuw!&<8hf!ThP2Txgc;V@{QxjT;G`bG7*t%bG!B)bL1tJR z0{q+%+Ki~I<@@)W)`rlJbB0O<^#C$RO_ZP!JfD>Fd;%Sjx*nTQhL1LcWZiVAqIub;@qtkiu{{IOGo|_+ zHHqgk&A(JPX7(5F6qpg^FMvaPS)S?LGUmUd+kF@LX;{4+&6*2m5CTJGTm)W-N>=AV zJR*2-Z&RnX_NB6)%ILjPqPTDQRue1liXku+@$H-A={W#~dwtkeFop#EL#@=<%CpYE z*%`+D=e+*D3G_6XXac@eE#@I2%0QnW3X+W*O+3e(H64d4(C|gHgW^ZH`T9caT9i%* zmfFmhkk7Dv*`qrT&L9kiQevCSdE|Ea*%e~^$+hh}C9Ly_eYTMsxzf69{ejhH|BAsP zGaKPFT&xSP{CkN$dF#~!V`%F!_AI$ud}KIrcaYYN&UluWF;s>@;e@D+zE> z`pMwPrc6e1YI-(YL1S)#DTl`CZiX!#`M#r;rAP7gZR9f?+dx41a0U@DR9qv!@MFJA zGP`DLGe*zo6yJfw0k&YZtWvVP=l5i#UsnuUF8ByDSpW0_z)(h=Rt;k~<1%k-@;7Fh z;+yB~xcD)#I_(;fF)xDNivNq-tVbE>nNlFSjw-7D_0uHL*#42!{W<1WO4(pSikA!6 z*E3&x+8}=>s3_`V2&e$gAbQy}h=>bQQN9QDx>&nO#6LO! zmcC?OsMR0L-b2SbfguX}yVR@s-(?P~dYz!S$_MfaSt*h4|QU+~EK z-iND3J{1Ioxd=0CpbD)1du_1WWf6d-A*^w2h1=jT?&UU)HKm>rk&jsAp~6O|Z{U}` z>wRBLs{t}_Kx{l(N6PEsV}iffR@pAAW+qU6ZSpo(YfD4vA3q*Oej0B7hJcFU3=&|d zZql9>cr8k&8KYAF4s;<8LYe&NW4*%DrH5<8sn5oOuF_y8hj{17={p_(7&NH^+F%S3 zV-;d`x7`)*UFdNq*4`W-NMnnq zdI|i3i(vvsOXiv4)_TZipdN&PO5hBVV5s-B$gVvd=T?nREw(5qd7oiVBcrIb)yR_g zORUn=@KpoQ3bx>P2&W-muo?ivM~Q+*Fa}p20?78un_RaOS4eI-iCp9O*4MYoL@|^b z*%Ry?XO{nCkF3c9_KP@`%=7>kg7Y21r{hi-nlBa<%gOSN00EWBYk8Z&j zh?@6N&K$pSUb=tpHBs!~1IR$FUT9{HZP`#JY1p=rzRwpR zX7}jNNHOQ{dtBBtLccJO&%luc0hPfSq%Yq$xK2bfn;P~EZ>~JTCy15py-`Y3XBLr8 zOJTX1zJK!fL9Ql0Il>I5@w~tOy*4~g#QpDGbYSWCL~pvcEyJvhlqJ#aA69a{F+4&? z+b*K%#?>IxVFt+X-O05-Glq?>%%{HpWw;-7b06aYmDTqMiug#k&#k%P$Y#j6b0eqtQh60Z7Pk-~;_ z=U1L}0po+RdyoHquy&Us{@P~&zXAXQ$GzS!FoujS_`RtyQS7?`MPG+LbW&#MClt=YEAyF-pH2|ExiL2}ihKsSrw~vj zoI&n#sEn}S=5*WBvW_-rJ&1DmEf(QjbLDNZq+p6`yrm5jXjf^_c}I+J8aUPW05Ax$ z-bsTooc;2eRxUlPZw@c?c!3a9)^#jtfJK25Ip|+ z+bYRai0@!0Ai87y^A&@MMhwCXmYLjZ|6UuqUqR|&42t$quG%Res?FIZ${StRTN4II z`>RygqMu9p%PsRm;pimz=S+(LZ18RTr!D zjy0tUds(Z0Mx?MMkYt2c?W5V5dY&Sm!4Mw;s(~{+219XXD)+M(iVB|=wslz);d)Y^ zE}%-!ni1vXr-z)cIj>(aSp9H8m?2TW6aWKe!VDRVA<21^A&&OP(Hk~~*1NWarArP& zwBIXNbqBgbHsh+(HUXw#eVMgXBi{dq6k1N`kXu1G^PKGXLR=4juU+Wg2-z>>&-M{D zKZby6;S7pkDCU{Vt)D&)#!Xh7LKNf~uWr|%7vq% z4@`u9Wlc19;t$%=JqWoYeZ}B^@(W=GS6Yk?fg0C?HWg(Rb`|)8 zo;j}D-Iu&0v_Cvau&o#nJpquRp#07VdQzCdhRe1Od!v0Mgt?r_r>)3z=$fmSQOm9d z@)_JN-@etu8I-`#r~KE?NKzRDx91yD+i|d)aq)g$cgu9NKuz)s?8H?sx?*Tl;Y650 zuFwGh!}oH}|K3GQegFFFt9t*fYw^}k{NlAredx#Uy=(lsv2Q+^xKsU+5+H+|pN{0j zZR$#EC12@=^v&O#3BI($yStob$+LMu@s9GyXYg%=fIh<+o`RuK>%V9k-Mtmmv=lJE z)Ju6-%_}*tgvSak@NaedEk%60V(_#_dM7@k(4(7~w^ zbYI-{cN3`XRM>|Pvq4yO~hW`!Br*_ zT0}lWa1jLb1z%mrbQJw8{zGBcMM7+D0x-|R7zt;x!=f;m=457qon_8;LuVdV$ z*av(tFB}g*vcxO#MT{O9`&8rCI{`8*W|o^RX?rw!CfII?NA<41*MF)_5!`(Xd(VOK_!@-97)oqlnORq@b@vZ=>-o2$*veI zxP%a9_;&9%0EVA+7ELgQWaS?!d@7XOpxkFwk9q{NafLx+r~c zsMdE#YLszO;(z?sK{e%DR*+24+2WJuk8-##elWd4ej17{pQpFL8J=Ix1U<@2OO#r- z5kJ0DsWf7@vM2TgCm)JyMV%w@U30r8^NIo7iuj;nnPJx7|6Uv71moji3=cYACrSEL z%xPLRlp1|UVW_G0p;dgPj)pa1)YTUzvIZ~>Z>O(0F1|{#FX#ZJOvYjb2k*v7E#6vk zy$C*B{6n@9hArx#iK0r3yk^e|fh48D`NZ($7hUN5C;>@(X+ZVpRG?X4KONgSXuhVs$ZCck$U%ohck zh8i-(x5`al=Vq8uZ3dX{y*Esl{^BefAC7Yz=$g!Ak$`-LhRdNcZEyyS%P%DcqCxB= zLm596vq_=?I=TreCLUJjRRPw_4ywVyv};!k4&w|6FG@%91ppZ0@kIao`}RFD6z9H8 zv=k^+mC*QN^n=ESDv90rjOPL8CCdDv1wf~#TXK)7eOSGhq<O~P|kR;pyz+mflGz3e7a&o`4bZz^rj!P}%-Q#A*BK-Khyn_c`N;)OJU`5(M zfQu3VgSqWA&D61;_RaMtiDW3pKI+gP`>8!1){bd*>Ke7kPeZ>X1k?d%(7L=>&nV#G zfR?EAP(PF0e7aL8fvR^Or}JoGSxiUq?G5+82i<;WI0!QY&9Q9$duL`f z1>j2LB*kfN?tTyy>5VV0^Zr=y;44{@QlU4UJ3xl_hu*)3S-xg8*QTYKJ1W{yFPm$A z{q28ak7&H~OYFlo_Nplupx1gmFm|yKejqAG(yF~(>v+YW`xJ~Y!%;#$0EX^fUPc(h&7v&B zydk5lqd-ajjwd5yl5z#9INR^Zc@|tKh_l*h0j9yzee)N3+~-5k+PM>H-KEpC61k?>@&;>)a7)(N3&1BbdavnLMe;_wsYZ9Z}eI+jD`RkCl z`4|22|1(tZVJ0EWz~r+IfMG|T^ahNlH`WAdw#qmRN&sEg}#VQWsDS@JP+bU=J6e!%ARV{A)O@nwh!VK!REL;Cx8yaq$i^CXZ zO*I~wi1asPUked4WPYftdE8eyv}1)*>BF5qw%DKqkfHJ#6PJlQSyh6{ym^!(e~XFX z3X6@5n~%n>UgDFPqW{6s-XSvt)C*_O2Se%c-;rz4n!P#?>&6xAAMwG;x8XbzOUQgF z(K(~WQ7m_r2J2KBgc-mlHUJp5IgX}b3|-;jc2Hs2(69};>tmC|);vUAsMiG^1>n$E z%c+Hup#x+X`@J0+r$A4_a7S;`&chrv;-Fo^5#ZnDEYT{T9gk$vntng(I-4bHzYpf_NITU*rQ|xUbjs-#w-4 z;u%bp&t7wPggvPd8`q#M`nj>hP+xE$!aEhIJRDaDkbyL8@bRCP&rTZB{^}_V-->X| zJynA?gYjuovkboZ9wGk;qS*EO5YSgRgCQ9DaM5^B&ow%5Pxw=4-Qa^)5C1%Qwka~Y zF}M_*4cT)2bhRi!kE{?*L%-EJ00yX1Y1^e4=8-5H8Rml zcEoRAP>iT41IX|*j7qZzd*{a^E!^IZ_sm|Hik47E=qJuMKj) zIfP*hfxJUj98Io^u2zptq$@Y*YHj3R9Mi3j@+#^pIX;u30?1G(V*srkZ_>lTbylK! zMngEa6Z)>>U39^l(D{gr?5ujEmuNAv%SCAb&R`6NT12X)-S0%ta!Ftkw6Stprn|mk zDJndxb}Vv(q0+MI@BD@rOFt22po*~pz#u6?Q3hjpQn8)wJgGtH_JsWQkM=|Qm&}4Q zthZ@wXrXICMJ6slr>9$nj1_sve{yT}41Svon!-_is%7_swq7<+f)3ZeSPuDZt;FtL zmgqq^!wWF93-#_Bqo!~PHCfv;cIc6O?0vhL@nDcCWH?ZgThsn;mw-^(6NDM$it_<5 zd@zV&hB4fJVQ^aiB%@V7_=-+=ldC#%xovo{03Ymh%ZUF`nl2kQ`=!2}F-zsLGkcvt$(Z~1K5;kv$? zEX(`G4f$EFa}uZU31k2Hvald-?^^WIng>P1}PU%LaPYd4t-8Yy)5Wmr# ziOIV2@3rAg+jb(1;WloiHE(~6vhdjE2y3}pb&$}^$tTyB@c`3667>mn z?(4XU7DlRN0OpKo^V<=pu&XpMD~TbTh8ba701Th|dKzF1Hs9;~(!#w0rwMqH zb>1or-0e&bTe@t?b^c)*&**6*&}Sz2U0%w=p9B=~e{lUtXj5JL%rbv`au8qh1sx^B z8Jh|D2i;<#mq&Y}a0YWQRBB?U>wa|MgP1079ZqkOg?E^=82pF1l(Ma_^93_o1Lp8=cj@@59-@@5+oL>2ei~#i54y+T3>KGXN{aDC9TcxB z-;wY%OKZ#IZgq1<><-;5rIN7bFjPO7y82*MpW8y1L8o;C00XBRnHek%2CWmDknD`( zRTMo9C+|Pr#3O}9HH1WFDVSsr8^4mg0Lbuu{w05;vGws=i}4y=Oy-_3(`)TcZbuuT zA<`UFoi!@RXLx$~+h-ikUF*-W>aQBt`cf6GzqM<9SokoSIY6$tn9TGB+<2m% z0+8VzlRepa`WL!Lt^iJ!GVbJ{#}hq66ezj01*fE4c~cU|XVAF(2|591u)1t(MPW=z zg?6n~r#xN}tW~lq>l3<&A1zhSMD%SNCw%$pgtc7nBOAgDCsuX<7~s(iEhRNw|ES}cT~+(DEr z6+C;DhT?CCzl+xFE(E|pG=s_nW5CACv z_Y%1~y-_2nI;Iz<*Db#=b`~{gYL7^i=;xFLUNLk|g(94WCeBR&4CVNPpJ5EQ4#01{ zY53krp4^<>)|I+L6?5m8`Zp%UrdTJtDQndpfN9u>TO!t@iV$ver{#QRcHe`!M2MBb zUsPn#Zix;%yKM;h4EC4T#irp5wqU5dz|C=LQtmjV6ecE|UVD16&{4`k%r_bRd#r_3 z5U)2^3{hMS2s7}euqRWlC5uf{3efhua-x-|DrT!a6 znL}t+JOujQ^V56KvCC=p9@f^@(+{V&dB$(6N4#^S-v-Fww#V5=NzbkmEJ?4?5=tQh z#j%TvJVHaYkqU6PFdHsJej0o)uM&TQGuVTnb+y-C2s25c-CyGBppi`8U$((|EOyY? z{B`$ac1nOh`YH`j>NSMZAeUGSfI%ehNf2yNI(&)aCvW2RYsn14X#zCw z%N2#i2S18_z6+3HsM$Kz`R=#qlz~dsoHSEKF9i?P$G7pdrK$cfQ*r8>BA+4n@?!lg zoWTJMU6^dH_|Z;BEpj+xM#IpY`=Lxvl=;qp_$jnXNbOhX7U}*;CR`U_L`f^WPd^oRqCSvJ@N+DT zjKW3i{lH71`tpW_XFx}@HcY5?;>l?_ls!)A8tJI&Fpe$%<-YfT1&w^|T5HzJI^;9F zy?k^v2WM~sLuu{yi!tP$G6%*lgrR*) z3?xq%Dq#%Y#6Ah?VhulOCgB_zP9b1C{~|mx{l z;79KQU`W%OorN)&XQxrp1`ukErrwClI-Jp5XGMFlUKy=GIL5f4?6IK(utZC*Io`rc z{t(%3>RV=xHfAfk{Y<(Z$K>5Pb&T;xG*#q}(GV-Te4f4tXK(>SiO1qNP~YuU6O7dU z`4FX<&)@WQcVjGHnl~^yAbi8=>PxA@J9!Ub229b12mf9hE^5K{Fb4YQ>kzM$b1b~p z+CoF`HoT|ria4YUR}zekJhH5wIs<(PI-j)=yqo8oPfgxPGO@%EwOmfSAt^4Z9l-Ju zVuf`F`STmZs&7C*OK=8PFf@VtAqT1(^}5a0+YD6RNXqVqaX9=@ai`k~w%ch+*?&9M z8-O7QGmsoQ17IMsx+?`^*bQ8x6xb5>{& zE#d^p2%BXov3?Uxyw57){OWS=%`tj~y zS`4X(Zi02pp~Ob){s;`cjBoK=Uf9XCdFQ-on=Yz96Qdx-(9$4ql-SBop~ z1jtb9@j6-0pyc}|cD{!`ra1c(=E#{S0~6lxHRzvv#iYu}XBbe2fR^D59$;t{8&lpd z8|Bqe)Y;WYTjHS4@8ZkK@n7((2Df$lkx$b6WvB^4n4$OSqr-o%4VB&US}=y3_=%8X z1unz8G~x5do;TR0qU!j{R$B_uR4qrw`PuBAVZik7p#;6bng7%_rkp= z_pRRe@1rX%eZ+h1*=-*KU|{tuz=bj3wFd{6f0iPb&5#YQmVT~={^ZRs97E+hr}-=&H{tuFWpC%4VgWKZ{yZ7@rk{x_i~D;=o&w~* z-}Zf+_wyG%e}%pnKmKcY$WO!30tB=UXYc_-w~8&RQsg`5-JLAce{d}tWvA!z#25{P z=2QNB5pb6D_wQTe#N8Gw}X61HeGQm=Xp{gGS~@Dlf%C8yifN7{Z!EJiRJk7B5_3 zm3gn92(w&Ub`ANP-bpDZa;EEwkIRaq@_XCmRf3FSe zMo#~|Z@^Q19vrnylrtV@SFY(iwD$tdaHFT(sW1YUY;&TmtO_8*BqZ_kj-9Hk=>C3+ z^3p!n!!CK-0n(wE#8h^cm8v}C52F+(H-Uh*;0%zX#~Z4IJ;-NZ%7cJ*;0ys^Xb*PkmYJmCs<59`p7>)dXDb6& zDQHaK^(gfN780r=>MMq*KZy5Jx}k%1^6!h1`kK>!1IOw$F=XE3-XRP%JP#Cm+}1Cs z@?oc$hCe6griehi#gq&{1_F++^mLY|R!8yur*<4@`1kB7cFIQ$_qcxk`rg-(+=YAw z&H)H$7tRoPIYz@ijX&0mXKpP(hKXV=$M7qYi|}!-|D?h|*&D)}p!O>U=S)k4(=Zz$ z34kHvCs7nE4UUc{balr?TpXGMSn}f9dz_EQZVayYl1*5jN3)Xin*d~RA7b#|Ce-@i zkUk@=(ctR95>KbR^2b;m#3!<1e*dHu`3(FA5YQf+AqWi3eq_oiA>?Q9B6M5ids5$* z)iA-SQ;k>;#{>Rwt}|BhD+bR>#IFR5vkdhEVK|+*H=@O+IX^@ffVclJ1fQ>6S*MB@_wi z6d%@&%!;EO(P@?Eo@hg@egg3D6^(_)Bj{ z8M5@&%o3Z#ueVqh&Ivw_0`GR>+^oKQfDAcZ_#Z4crAMrnUU{#QT z&>p}Ug2B+0Ft4gmV;oPisTc_B)q;~R8G5V{KhZ7l5bN~c zdqb@0^$HjR^XD1!WQXki)eyt%m6oxT!A>lpK(d@BEtC9&wJ$Q`02vr{72kzK5(*?g zop>!ITDft@NL=L|af0!K+%!Yusqz%$7bOh`2<;)9Ap{KV@vS}>Q8@J6o)!!{n_G`W z!+wNTY+lSprN3X3wwdu~iG6(P5W>A7GfNHt1A%1+Ka8RG#47i*sfUv6Gy6KJEmf@F zl!CWZ9n!rhTz=~^7$pKdN=!r&cV~os0>|;YjC&WY*lvgqiP6V_@PYc0M$XdLb=Q#3 zpql`pJ%TfYUd-tJSb0_Iwo`RzM$LGFerdgj`VlIANmx>mdui3Cw!HOa8m!b%5M~fY z2?f9aQGP8CV_+70aHhC%VE67pyEl%hHfG9l|CcJ)=Ap9R#ARQJm52bQ0gswOUecu05y4r7aVuZjw_bN3xk-UP^Sf5@W64K***Z#A6C+;wl~rNRR{+gW#UtN}v>oCuc& z7W~GiB|cX^Un2rm<*rCs7w9jgLjWk`T;Un(Ef-~ z7#rl3`|7RtWBUd7Q~9yygC)JjI>&Fyp4L(#e}9973kX7c3TKD_L)+3ZP+2#YKN8-> zsIrxr3-R&(MpE*~1&cxYN?M8i%%7W}p^=Dh$iYKz7RO=E0vfKS8PskRhGd+Eb{yzN~OIfoS#BoUJr*iXP_2j?%GB zG3Fb!Ra?ks2+M`gp2HblUu?R9MChl!<;hWf%elN&7WHsHH1C08<)hbY1m4!Hu_6AK z48~T{2s60#lK%Sl-cTqVYX)NwBz;JAUCHRn?U^>KU-sYcq;p!8vlpuB^(>7iJ@y$* z1jrC=a_!hCd+o%)X)IrsjW{$oQ9Q%neDUY%OZ<$7BrW8~XNaDH(Ef%qM1i3-26l;4 zH+Gtu{g~;h$Qw#z^g)>Bhp`Gd< zT5pfzjD6WtPk!6N|B_t4Ys|NYMf$N|GiHVr5$7etYq9`@8Q!K&0ASd-`u^|a$&-y= z5qEtbWq|A4Lq9T@cLwxb`Fho@;%VG;bDm}&)E^)NVQc@&C%S7ltcRMNhBf?H(4;3V zdQADjdA{A41{}?K$Y&^Ufq>B93^8En9sYyh-lblFq*X1`R7~8#)f;(D51VZ90}8cG z9~SIi`H!J8+9exd20|t3^MCIROUWH^I}_7N`4NHVo6$<+m?ciCiAmZ1pY91O8w^|s<@3@Ne5Ape?)L`4n+bOp{3 z3x;lIqt-9ZWbUYMQ{T##okCZeq!+Z4GH^;Z$;U>SzyGI2C(0Hg%ut1*2Y^BL{jW?I zLwd%O=}0ef9-n76#0TOuwH=~k9jzX6R!$UCUg&u0?f}!kff|uT_4~_n(^b{dG?A*LZ207LB7?BC(gYeYj;$81R&MY|n}PWP*0awUVvcQVDF zq_DgdieWwk`VrJ}+hq3CD3x1_F+tnmu$4`sT&uroP*`pF1Fi-yd)sZ~GqjUKKp1d_ zcrf(*IRk-Z3%YSvvg7dPVe1tP@y??hjQYq@-r9REcZvUOPtUK^MwlTNG7Eq~P<;s# zmWJM`huJCtqXJx1O7T`>9)fJ22<-wSbZ7aozjPU5F24krhHvzzch=*;BW3M2kiqop z9Yr&=(ELt~2G7zb7LLY!nAJtntGSgLq((5I6E z7>-Zx6H|y-*j%>ga#_Sr?H#Bx{Qmdekj16Sq7^Jm4VCp{BEE7IHMtOQ#> zIgYGfX5uci4fXv7$Y6neno$-+gn7l5U~$7x(lo&E{gcOZIeq*DRp@HZHoTF~Fct^_ zVZj*^FIFtMjE1-0PF5*+=A=`7o%8V2d6doy!EQnFc)}#P3Dl{k{x< z!GtGl9mc>`63cxOnS4@RL7`Xup2;tYWF%GM*yNyEpm%buD54M`Lv8@gb4Z{*kticb z=2P2~ryOQjosSk%`+XJH2OF^8XCOZfn|C1~TsTAW#ri!#D}j5|d=hVeKefLS8@IQ1 z^44YY?t+qq(pqM!?$p)G-whf&h%c3Km|#OeL;3&zxq?FfU+egdiGt#yVxs1#gF=Fe zGJ}=#3&x=6PF3v|#jpMdyu?#yMe$=LRx{kg>8kGT2!|MFb|%o585DhDWN%4$A`C`? zcB~SPi{x}YT;3F!zP;gJrvCQM_7&ta9JoS2cyNXkFf`>_&EW4Bj3(*1d0b!);wxF{|5TLWOYUEBKi)!wqpfc{(eIDe0yhmCJSihmMB zu4aKYM`gs)!}cQYT><*Q8hyKKX=wcFl|c7|kB)MCVxi6&euX2HGK+nOxIc*m#F5W% zUIqc-!x`Rzq3=X9%+ZPS*;#_t@~WOv&JL28c%C=ctO-2%68LsO_TaK8ZLIns%n;L; z4}bxzll=EW?t?Doaa?xUt6QEkA}!}FVO^}w)HbBA=U1b--}1x`xdJRoz5248C$0)R zUNgJy!D;nBHQ6aFFe|(>xChVG46WayAe})Ha~lF8fHS0Cv}g|-=Xg<-qKF+E!MXN{ z8{2I69VF&sGs}42bFU_)Dqb?!*^45~5HPXhS4t)$a2)Zh#E=&CZby_V(lw4HJ?(e#g z&p^Zj0TIF(pkOFtxd#f_i0fBVOQ8?gyb0j?dxTxD^3b;;@6Vc0q@t}~GCU_n{0wW= z;%(G_?+qv@PFpYr1=?cOZ~nKWD;KObVy-NxRZ9)3hKzDHQC2h#@7Wv%17rwwBBj-+ zp8t?OZT|JA1|9K6;M?9vLb>#No1l7v@(0KtYb8nP3;_|r8PdQ|)`$Z3GebVtn&6b; zb%y>p?ugX7)FH^u8mL?G$&{1vWs4^8L;QCG`-u|(h7w3UH;e(@@_riGl$ze$;m47~ znO?$72LU!|n@8?+SypY`WZ(P%GGGwWr)GWk7)i0C0eM;B+x}=G*Pn6J-lvf&SbF?q zjT-rBps#>{h~W(B7t_VQtD0sgBoeW*3twfAKQhP0y+Xo3_DjjFiKiMhQ|{Si8muyn z5H3p7)D-|2)JL61VGNmZ9lBETvU5?wT$cvFR4b#?f){V$-u8@hWA z9Bb5fUp-@9)2!RQE>f3R`x09sFnRvxtGsr%(p2O#upL4`ByffdFmy?W7)ywL{&*{v zL3lE&2(QKJXH>)JYekxZEN)IE!JmZ-U{4%)n=Sk_n zWD4Ol5IPH@0q6~(q<;^{?DV{Rc!+tx0>JAw7!IG zhvkUy*kD#VBR>t|T@Vl%oZ&qfN){{0W9`#Pd2}cJxgq9BUg7O{yAX7Oh zU{OkYA9k{JE0VH;%y|bt#rO`Wac`7Yr~7yn)1!ber)GsqJ|K;&?SY%uf#leBb$ zCI7rGlW^)=XdCT7g8BIB_TXzG;!wlg5}N)?hNm|V5l(|8-){g6`>4BOFa`!ur&2XjNg~C8*~N>lX+(& zF}6^y4sHC78RRpl>p(yhaE6?VgKjaJGE1%Jy>9W%jyhF8QzWPzUJ9D`;~Yzxc(q9r zE?hFW@gP23tT{m9%D?x9?$WCu7(?YJcG9iTNzwP8g+5FdZIHW^RXRoO=H<0N{4*sWLLKp=#Ab8;02r8i20p*h=<^$SJl9Q7?_6KreF*wb|FcW-@G;NNwE~D5HqDs+@^E>{ zoSX*elz^LD3s?|~gn127GKnJGkYd92l0tf%hrztr6}K1T zXBqLCB2x?PFB$B^%n@$Uq}LPyFr*1!8Nt$EQ1o%^B(ftPy}loH>i*(awfkCeEx7WP z#8EO21j|bm05bSEn&Rvqif_d;nKiLJTyfW$E@(xuw?26Mt%zU&%$ALO2Cp#)h!)OJ z2!=vB4o{98ayx&o(m_xo?anX`xerE$Hr|ot$!+<28(RIxP&q8Sh%m!yLIeN?kuk>! z7{e*r6{%>aIA+<80>4A(6G6nnLUC7Es>1b@rI}eogdPKAh|JZ*HQ7v`NWv#<+&1~a z(0sC_927wRz0(Kec|E4x5%~=M*C8MfoT2DqZFe4*s0T%421ie1jgG-95si2K>MYZa zO(y(#R5wC&KU}84cgP-L20YLw01Uc@xgTK+Hd9yF?@9y{FpZN{4){KPifA0;r zRMimnyV_?ie0|6obt`2~<+i&~=zQ*`f_?##9M zs98O{97vOUprt5;$2Mne^mgqRSs`WXJ}X|5qv50mHz9f zq_y4H0K^a@^IM>=+htLD3|>N*L0ae$0EQUalIt)A-pd4=E?TTMfnPWvgA%Aw9O&EgT9_vdwN}kTIsqWpCOqN z0-}dAl!BoTv%s@kdR?@43ToDV+=|7nN%|zMARgC6elx*lbk>>WG7W|=5Kn{NL_7cn z%!JY$7{jVP^YGn`8Mkv=48w1GdW8E07A*dAqsiy&?2@#(pIQJiXmuoZH=6i~?JL!FMrmkjBL$_O*~v(sVz zdvBm%>Wzgl@V{0+YMWrnR`7p7ZkYIT-HILiNk;sAo6HDWmLUA^C;-#IONTAlz9H7c zeZIOvbz9f>?(e}5nj<+f12-}EYr{XrA)lf0Dg?v?XQ;TibY;BrL#|!i`(5kJj2Yfw z=Db;_7RMKCN9v{{zv4YyoG*I=asC*>3~@6?02nyqtLb43YjM0^wo68KT9=3G`F|(h zb)|X49V&mo$gk(pz3e4Z50HUqXqZk<;Lhf!=d94`r^US^=rPtsbTfGz_^a7@cEq=k z&(L5E0WrfFDlZ;bYtItblHwxDQcrFVT6Ej(G3;kWEc@S=SYmRgy4CakG7Xj@8wfM} zPD%&BP=n_k4r7SiHoNOjqEvq#D6)`1^*r3BHhlEWZ!Tkwarr{EAE}c78K|3Lx=oAD zHE0YzJHE=Lb8bh3b{HhpRfZpzx z@Fnw&8Of;`Z3>S0yFk}y=+Eh`j8wgxWNG_gdBgY`5!Ke`ykJ&TX8IK0pjL88S=wKr#Q1|Lg$MFzy5avBDWXfT8xr-KB12pVib} z`LP{#*6fC0b>_B4*U-KUA@?|`+gJHhl#~!ZN-T$A3xFYi&e9IXV2ypAq#N5J^_XgO zyTpY99EaO!1~LU(#X_ga8wY<46oZ>k44l89e z6H9TC&oJ8y0kOduYQWIYT#p-#QKn@5HbY;~AdzHvrSn{ES^N)=XH(|3#x^N08G@7% ze^R=-R0x0pFAVhexLE9*CF?{?D9_zOmurqMZ&ch9I9|l@$VFhcncIp<`5AYEeA_DzogS zTqn~)-dy;BIP}!mP1BQy$04z+c9#q#7HbF>rF*?U0Wiq%DgI3ZW25%UBZyjd#K=iX zdAl|*=J48Hin7iL3w_5O=e61tfN7v~-W$eG(f+Q*ZV#lG@FF(`M`3LDtCd&d{R;4r67;`qCRb25I}|` zr$@|`I?;C*IINWGYo6B$vVny2S_X>6OD)A2UhGaHpW$#00^)!()L-mxaF)|aLea#i z5n-{IbjQPax6Q`iu2HDT`(0Q@q-6fj!TN-XEQA@7%G>}j$k{ahz289MuB^^XM8>hpttX5!d_>OBaH&ZM?hL4?LA38Dd$&T1E<8#DXy_>&Izumm|O`aQC zWYXyHpcLs0QYa!2&`mf)0~qSj!BAoUV=}@nsgh7M+EBZDq{iH51kaVgmS^Qw+xOnf zqLdSj_#mH&vKjykLaZHsheIz*j+q`BKT0aI;}S^f^1E6Rvod_!gneD`riM>q8)+jz z2E~)f;4Kz5diGG_pCQT}&rfa(>O=J+(zm~pj4m97A^#|`6m|*(#0h6;1Vf1es4W6* z9*J?=t1=XxM=;2m8iwiK@m%O8Q_wd}QXsx$FqS+)I1R3KX8;&s-0hPi?b_dMo#6?!8WxvXs&}7Lq)?lxu>A%jbB7n{=rB zDuvrD0MnrHWBE0u<))xu3evdmm`2 z+Uxf8OiKe~$V8VZbo)v1sU!Q!#2xub!9dlN^c$(fX)&+6NaX21eMCM32O9*$4QKcW zhVrvG>K)#CEpj~`h2*n>k1U0EUOugL$<)UmtT}DRvP_o@i2>dSGt~3o;Qo72BE@L< zd%pqXPP2!}`aaQ?1eAH^LK*9dU&tpJY24bBIjYsQ@HGY?gL6ZJSVdi}!giS#886pV z4C(mBJ*Mq!|C$fZ!j2*mhsbBR6Al6Kz!_S>(BOWoCR%%!GT8`e#dqN$25LD!BfKMRLC#zW07I(g^55QYqY1OH6ZdyTyX2#TC~vm3r_<^Ad6nOvM z8~V^A31AHG%?!w`r#*gToT^a&v{QQCDfps}hJBnVsHwUB26cZiz@n67sOVwZ|4QE( z>sup-mbwD%M7dLzCgYe|15bsjei9z?i;^Y>1jG+#=mbOWeYATTx!fGY;ZG6m(T-Dl zC)Zr9tT`^tiF?JM#?{>8lA%Zz@tdH&5FG#vn;Uo^U<|R2w(k=eG|I6)LtV{+)$9qX z%j=5Abq%{3baah(1uX$G$dIBwGkGxR7yr#+WpUw?Jzq+z^CUFvb1lb{s82O6Rmf-1 zkAZ*$;0#?Cd*4K-IUW=b$ID0BWa^%gQIq`ixk64p;YT|7tQc$Q=F%m@`?E=edjsiQ zG605*THZhyLjv1RS&L3nKJiJC4FTtzoSicXQcnD!$>T!7mEMZx4*(g`J2~n|KNmk~ zu_k1pHrbl4(p7F7g)0tJTDnK1)30MAd#L2z|i=Lx9&8AcIuIVIB8pbn3IpFZiIfpY0AIP08r}eD+@79hUBNTm27S zX4u<8K!R|Fo{Kdat~Ja9b(3DMoL7zdD!EV?X&SOaqJ>_HZr6OYL+AedA48>Fuq46^ z-lfd=|K1z0EmbUG3{sqsM`F0SLP}$2f^H@P59i7CO`hF)mvQ~hlC|pMssum=#uR^M z+tNER<3_IozsN{zfy-HFO3P^)vYOh*`fQGykzbUaO+rBT;0(QB==^$tg!p9DBRr0L z^^68E+WlJ`vnG}cCrKqiTX&e={+YvCfKrAqgC?6L00zZeyc;kEoT6`Z1B&|OdgCA} zu)$=@8ijdMW#3Rn>^!SBPT{v*fDA^y);u5cQWxj6*tI^BhfS^ij(%J8L*cen?TV*~ z0arQl8GL0Sp!;x!J}`8-GG@659W~fX#HsNO#dlVF@VQ1%!U%jc)lfy){DD9;RM)l1oUu`5t{v#w?)}#6 zG1}=wp%qb%{&W9OpTu`Xk4jGk)^I;QCH-*-@`I1Q?tn*bP2f19hp7{oL_HM`bK@P}+T zZK~aL6ijq3lXcpQJ5DC#t2z~ydI2yE48jos=cia{eSrAXv}fC^`=Nq9DjEM zNp-iCAfF+U1p*R=GYo*Cl*U3!C|7@2V<`u4q0GPVna;JDrVtwtH}d_<$?&#;C` zT{?srTuF(f>BAlD%C*|p(VJo{#UfQ@ncE^plRaP8ic0QMN09H2A0 zdA5#I^39cXaLDiX#+glqWcw&SGvJ$2s3RX|!O(a?e@2(A&jcgPfcx+n0ESF$V>B3pvqA5~&xd#& z_t)9SuA4L0>&ft(#+~%IZtgu|7c}O51TYOAi^bS^W>p&CsMFVwDKAP=HR3yB`2B1iV&tgE8<-e=-?+Y-P);93~=uczyXMRjeSfhxP0mi{9&W6y-p_ zH;BG9?}tMCGWlH*;{U<-h8%AQNDR&}1cv%V>n46p zD*JurJwSPTIum@iRQ>CyP?qzj3A2QV1_QB62J89>gc)AFJp;h7poD1;WB9S+ck}%< z*+i9HR<=$1m5y89=k1Rg>YCOfEIj$e*<*RdO-pO&rcJ42E(ZN>2x##WFcpJ1Tula|t&S_}G=)oChJx3$8Su z85X}}a5Wr2nBj$zIN`tdh6l_a{9z1hbMK$)qq1u-M)^wSd!2H)XUt8p@Xd4Q zD+@3IWH9^obtPsvg-HQg$62$K+D)y}^*q8Sh^ye|Z)gE^*#Yv4QjH}9Bmrj_0YhE5 z2uSa71XN8vP^w&IuA9)H7_tr~{U%xxpme+H{@Ufww~D7;=m;~cV7vstAQ}+I1Y_9q zDXDz|_Jh2Wej;$oXpHc?jGX|kQuW|5Rq6U__|5A88QzbIr4g|WdBy0h3%TuvXNoO{ zCgIo4_~HG+?k@eF9)^5|mWzq?l5mF6i*dN=Lzxznj@>Si&DUo{qzw*tXEDen$#suq zaz>dVNs9<)%MJK10uA2uKRfFm_Rt zXy@H5vgcOF9<#(&q&upt9Qyul;-_oBqzV$TO- zKz-H{p|JHk|0ZR2wa<&D(&j#l0@_!WL^MXvpdJy>xU*sVm z892iP7)m&NU-f;qm7t<_XtMHGgIshv>lKu+rynrB6?<6(Eu2} zJ7Iak81k>L-28A=>)VdbH#CUw&ufgnABUhlYZe)Mx*l&H1_50vBf^|Xmi*9JxqPxI z_}U1NzbGWGNW@}~qyeQkq)WZ?{xVCemCWDW5LkU_#ngbfiJCndxv z?bq9vsd{4wuTt!YV0m4p!4ehmGpq;9695?O3hOFi4970dJ!{<^XB$v#ExS2!?4@ta zH&gSgW)z<=((R7o?Ey?f|5TuEd@ZqocLd=q?sUSk@~()_A&>Yfna?Wk`u4;o^3$*` z4go!YGkm^S%_?_FSe%orz)!gtXDBKCk?@i9gDK6P#HR43c(CXI!zDwg2jZKq1c+&g z|GhWtw+bi17{HL^(*vo3kPr_e?AQ4^x&iCEb$Fu!xN0Dw*WE}-L#o13+MQ3 z$OoO0%wxySz8g(sqiM_BPd$78)mN|o!DpYn1_($F&M*arn$Np5JA`CGaIPCu5Z*BS zOnBX}d9>|)XgrONl*Pf~pEM*sC`Y&`?V=k2V7SsGUk+nHT`17a=TTe5CZdd2oQN`u zvAn*1aU|1>O3qxvNE}BFAcHBGITKyUE8swXjv#2IsDBu5%JQukZlsLZuzDlCgg)}q z@atj#s63qE%f-Smw(zuLUWtd^iMTwIIYO;rGb9e7o~inTUVCU3*v5L7Y1rXOLzv+f zS_S|HkAPp#{xTTf%lN_*Qmw$a6vFw8>3Co5o`7l5#ysgc&9n9L{`UYGXpe&Qxv>gj zpQFXOrkn7RmO;m-+$njg4}QswRIY`&Bb`ASqZR^EfHO>kp%}3w9cViNS)ZQXByDfu z{HoCtuM!>8xaKzlem*zxzT}d@Y!Dw|hHqG_02sRO^-jVV((ZBwDQS%un>tmNdJ)_G z9HI@T!@&MIL(Mt5iLXAV1dw4#vHqh6gZt->xUq!-+-(zChYDV@LQd5cw?LySwSCB+ zwI@w@F}U^h_^oW1GZFHWYQ#vMbok`u<|Tt}ycNO> zOcXas{=GLqH^2S;-Y^s!AN;PW+SglJPOgDv&*n*TfI*hMd%0M{-rl*jNEbkcQI{^R z52=v7!LgDvf|x)Fo--?PA>tam(tdW%dJ`h#|89_`sDpr%;0&{1Xs#0vSKjsvX8YKZ z@HfGZ{Zl#|H7Br zi*Oofl*$1xD2e%r!x*r6wFd&FiP{Hn$W9WzbCLb5C}*)WqZ=q^#xz&~my-ibL(A{b zx`&7Qz7>o7_d3Y;z8AjyC@G57SerGjJy0n)B8_|owu>nNDsYB*Fw|T2!~H^Q77W@R z;a>{EFKXSc^IT6|^eDb}^S(#^l%?T+43!Ll%m_0~xf}vum^uB84`ZlJD=rljW}bID zTkP%kl#um9xe<5{K%^t4~VWem-Ypwzx%a7+31e<4Xoz z+3N^1T+0+9{rBEb$oak<#&BEY$PuSQy^?2F31c_DW6QuSG?h^WkNcUMI>l#yRG=4f z89!kBhPHaNvg5=%Ri!r-7h?0zw&*q1ek`ghYy6p8HU~*yLpanubU@`l1I57ee+OD zw$Utl{xJ~w>-VH3)FB{sIKx*kwB@-0T0w2j_bfR(m3lfpu%`-#?Z)8`ZEE4V%=tJ| z-b;o~{-+41;oh}201V+Is7Ek{Z^S#)5jP$;R@9zHJx({yA4gA^xWl`7bOSp^(X;Yi zFhB-62Yxiiw)l_VT-#oa3f#he*2wxu8PrxHuce};fG;0#M(=)fXM z!Go-2OfrRamAotD;;mkBH{xG^XFQK^FnD+xxOK_!9)A{L22v~RtN&hBV^rgH*gFe>8fOm`q(qE3yZ8#84Knii1aA}LihTr0TR ziU*4S43HsEiC_vvogr@j4RL2K(McQ&D*1%+<~Uv8t(IT?Nke+bXV6`TfHdI@D;Gs6 zw}T0iK%0ke{u=e}+qG8BUSbLzre}-AH6i5Dag52AY0&;0jc^)_$)f-;m~BiF{bhKc z?>*B(Hg(NwSlS45lzb3TUfx1s5ZV4}%(b9ChZZ11zClFe+rXRbNp0S*u1%kgb8Qxv z8y20_-&Htd=uaXYKt6++I|TFy&aeuG;zV%kec@q_kg4$G3$->RF40rwu)m@Ih9tW* zaAW+j{w0I;VIaZ`6CPs#7(zCF{T-EFoIO;zyWBl>{q^=KE=XU6=|Hte`YY&~Y)8P8 zUyM~l02zd5zwaFH*uU%|3(oKz483~2R!&3-?F@6hOs#=WuRGw2*VEZn ziG_OWX%Odub;M;F>~F3j%wVHq2!NqZzp4esfQvau(t^*f_h=-M^2-+$^>yyYSq!zE zmR62W4C*Xe4FNK=%l&wizr=`n?M65SN=d`5rOenoljM>DwZKdk&Z>f!$S+Dh*B~Hm zIK$e-$U{5!dpTcdf6p;~=C0%O7HR6w;XD~MP0UC)J$HFB{^x+qGyiFX8G^^t0Wicx z@|(gKXu~G(j{Q<^KCx~oa(0Rop}fh`PS*88iS@|jil`AM7eIz5*@XU7bswrN=QT~- zH6TmHUB{HFtKUhPpH#kY+B`o&K0`nu1f&CJ_;E1~chJOm-Ad(a=#d%Anfw-o{oQSE zOvxwS4TgHlGa-1;%QQU7U__XKUw;(*<&i}T`gJ%kYSCw^J{C59jIL-p!MxkP^s?#PEhFy<ORYKH@yzE>FxL%v7yp^#VC`%iAVZqlIArYY>;Y>r zYmPDQX$2KDfj-H^$d-C*bW;Deiy-nD;szifJvhS#7+S5MMAuErt8+U8@4Jx?8${xH zR{ky1U*Bh}Dntr)bpHH`{&Z~};WUW*IRaoPh~CD6F%0soMU0(m7EoVVL(w9itf!DX z8}QBVOF4=PQXulI`v#D~__J8zfu``GV0)(KT^nmw2gvZ7A1^ADi3Fb%Wr$(OAfF-i zVuFl5oM96T^$)AbWnm(|qL}c6Tg^iCdE?=$5<{XuwK2Y@kdB6|#>+J1KYxNS1C*f> z0E1|s`X-DaOOW&1)Q8_ygPHz-WrH$G>?2FRe-LmABb82Tt! zrY5}vWL>Xm=qjLsmq5qIWMeUm(dmYKhU{Gk$NZUR1I@_Ra__d+`Z8^bz43$w&5I-&!-E|CrA)94`7{;Lei!hWdZHJ`xO=VM{0u4@B zwsl`X2Vb-dI9gTq7_9~%L$g)I$J!}pmaa+@yrQE;bo$f9dxYvbIEjWB_i~H|_L0v} zaC4aVS*hN}4u@6Fu$&t^HBu`(Au&2pdg0bXg(ZeLCInL427lnA1oT_e<# z-VvtF3ZN>_REqrEtS@LC!8X<4(M89V`5zRe8afEb2+pt#hBouZ8PUAo(Dh=Lq_Cyv zB)gZ;WPX3Wa$M&g2?f5TANgfbvif>}FvHzD{s0(8IivsH1kJ(-7fr^ZAHp{C+MmA_ z9X7}kuh@AtxML7M5#L9f8t5|0MXYkRy=&p!=OTAmg>wVy=pIsO8lL9{`7})4&ZaE< zAGGL}i+$0?aE2W)^vMG?Ux>Tl@YTEhN zF_U!dREL=6quk0=I}wM4LE&xm_}k8+-ISilFG@X15ReI+VfW%*bg&jt&dFz9_Gnf| zThp?$#-%sdyKZm%HQm$=Fiz3UP;$Lw##Ug&=Zq~46vOT zei*$*KEuVlJCG@yVGj)59h&70FpW^ZAuq@)QB#MpT)*nS@V<@L^8B~pv5M5}Wg5BR-xs+#=8!!09*9J zyR}A7YP(N|iq^h-$8PiZY&Bj>rkhh%#w2#TgezRgXZZ300y2X$?1P~aSh~r?;#ln9 z+>W~WPVnjdA1~Nq9u5{dfrd zRLzqyl#tJ`L<0et!x;|1P~w1*x7XAcp-~i9%x!y3mO`(~nzcR~IbGQ+C{Y+wessxT zRwj>d8Y zT9wc-ws{Z9wZ8mWsh{|alNo$-5jxy-B`%Sm*73G2@)_2vAfP93hC?uPLcwOg#p&ax z&=v`Q+K21e|K(N_+yf1Se zzL%rYD>5Pxe^P3^^8^4xN$t@u; z`%VBEsF!97f{o7arKjZh&_1J!n&1v4zWIWd;;wj(v;NZXGV&RIU0leugfkppEGphI zVPcYft^IL&T857rJ0ofP?Nb~!_YF_b!x{)B)1Te|efbdKG!%2^0bnqEC(jLI@Np{( ztd3sf@T&F8;;7^aFz9pmMkcDBm(pQx7f6=C0gz!x?c?zK<-=dKsV~W!CQy~@*}vf9 zyg!Y?`)mWr4f19|I)e=6#b+NYIKv4TIz7GReG61}`ZEi6o36*ki;%FYAaXzp`yKb! z7bdSHX)b$1_$$OOD6Z{_Y&cP#M-KvFlR$PB*P-vQFZM!*}eb1ub%9snB?9 zVhy_lpm*P@c3Dg{1{9fxENZ#U(H#5rC+MFkRz(IAght3-mC2w-J_8Xq1Y`|oI0Zx1 zTEJN!-vA07Gz^=HG25bo=A!IFoIX<8zi+$I0lb;!SBXHLtlG zliE_Riu;$P0xU{t22bRn!iAV;PO+V~%)=51eNuz1dG4EAFA6<^b2E`YhgF8b1p=~# zGyDQW!}YImb?m-aqc+)hle2f!4f*9tfIFgN4_>Xn0*mr;UotFIB7QQX+_w<`Lp2x4 z-!&R!Jo3vP#@Ui0lmTauvcv+ll=yPTq5O}oo}Y%Z$G&o6h(gn_l|tL z^1IK3qTV))-{|i&UotovO(C3yp6n|$|6Y_Ro8r=7z2Vt$$aAyY2ag?1Tt+A=ER~iM z%aq3SZi#FpzDOz3j+g+*5M?3vCCj(KD)NN|i4&MMHl@mU+(=BBjHPi8kBQ{83I4c z0bpnuzXygf>~clduiuz0Z#+y-W>fH`ub!FzsIRXeXe7pJz0K@WrTndb#Wc67#zpkluC*_K&=PB2G zRAouj0?NP&dRfe?-(%-w0Mno#YLzFO9i6?Ar7whW`UA_!{o(YzrK<9NiN`{EUDqv; z&me^Z0X>B?pn{=u8krG6*l6qhRv{uwSY%V!Z|;~kkdZI^cs(27|1>J+lEKW26k&$# z$0Gn3q~5UoT^x|}c)Z%ELOX@*+rZ?O@}O85+UA|;;&GDwoC-z>1u8ax3`GY!G($VK6PXQt0A93u@nMwgfpOB{B9WJR-UBlnz=cylR~9| zt+{NbHtaT^Aw%C?OHKCFEACHkutR)GKzceA?Z5Yi05Ux?SQ-MtL z+k-4jA}|KD92&-P)U^*#LlVWDv|G zet5FD<{JQpNZmKfurz#Y`L&gHGTxC8dVy*Ef*J*0*)=+kC}LAw&? z$b<+Q1tZ-U(U{2+1SeLt?%a^G6m3=pI(afvI_}6q6dI8JQhQs1;w5jrS{nu4i5!X8 z7eB%0C^5*tbS2|{F#z-#oB``14G*7(avM7o;(#k>UO2i+-kcN*x#m4%nU>4*J|z0> zpKsCg*+vL6kfyo-V9+?th=ehu&+DMwJEpS(`N`VXJ@(p&Prv`8D&@O5N&Bl@;@M3) zfN3DtkuW#AI^_72U++t;&QcQzUWcT=lBwSJ{dpqgOm5^)o|JiU@!7`>&VUVuGV4I@ zX}=9AvAe3)pMyKs*YV~k@EC`jm0w_0cJTeq;$P6(9rZYu{!frP=W-yi)W%+MP1GMSWdP zJr>>ddxcL{8duDb-y4FTKtS$r1{^Rn&vm)Kjpf7pucg0F#e792%ti>jZ%v!Ue){3S zAsx{D=Od`C4B}tkxU$ayFxXYzt%5OVt|eJfHk=GkaDFs5Yk0*&q`q}``eIwL!i!o@ z7AjJp!=Y`zGST3nV|B;xFLcD^a7Xsam~!VX5iC`jtuy5xCaxo&A&LS5@_;kof}v5k zq2eYw;!eXwoI~pA?@4!q8=5&$m1fM+nG3PGp<$Q3!Bh(IyKhp0(scjc8(eG#i(w3B z=$-1)oXokS7@;_lg}zIgPy#<+HQ*uz4nu&JR6mn ziuu+n^w5(_2G^oogo_g1a0mc~BX+i{ForKvZIcfj&{$-Z`pv`{oR}%=;bVdD)Jf9pF==ia0YxZ zw0PBasBt3eymr-m_(y={9L4ms6y8uWZ?6!u_8c0X<0Zojx-oQC*BWW8gc^H`$BPqtA*9AQ*UL* zDDSjhJ9N{r}N+7hX}e-M_#A1xckv7#fi-=~4mdZl$|JIs}FR2?eC2 z!6Bu)MUZZh20;*{8xf^BoELGr zTVQDA;$+T&W8vu{LCoqasveF=kKIB3ZINoE%+r)F*eri8U3EKX!_9C%5(mx|lnUv97x#Si-|GlVVVJk&K6QCzEZjMNZno7v$NzG4INn)4Z zv|^t-oLHOtj3G#bocqLQ0`X~RzZhNO3uC~&*k+>g#Ldd-MP9<5>DNF$tKgW#U@51> zsv*L%WWw3QB&5sU;O1ZpH$$Mt5&(wXh{C@udNs?gU9G!93{Cl=YNU4L`z>%nR^-NF z*LEq^<65=vQ~=Y^GtnG(@HWk9!8(V-lY^zf?niGhMzBzeNF|b@a_6Crf#%Dzj|t@ zoV(x6haijtvaQ)s>$~qVM!pWLp(37PtOWuB!x-?v&_>A{j)Fa%iF*A;$nHCI`fADq zw?8#suPU`G{QQ$(@9ian7M=^-X;3!U+rwH}RxdUX7EE&PORur+%%O{X!pRRi-A&;>mfo&b=pkA%#jZScYc!t@F zZ6^LO1_CftO{L~ESu)?pR^4zZ25%-LTx9tCM8u3XNR7MLb3I1;lA+vD5pIUw$r=C* z{&>iLzc=KV2dJvwOC(Mc_E>$N;WgB5PffqMoM+m!wpY8!^8)Cw2J{@GsFdHSP~Lt_ z(6q9q@^iXge^D)eMOoq)<>r&tIm9!p@IgQj7y}^~y6-)8wmOqN?DZyxynr$}kit+3 zRizbYCR+)WC(|+S-6ey8dNbS%C@rS|7?4&srT?aZY<=`A`)yi@Fp4`YoH6zDN>Rm1 z&v*z^x2g!p2GRKeron`l@wPI@LhTWjN;c8NjDk;NSdRllRG~l zpa2*H(FH?j$=vbnTOT<28$RB+_9WM93EQG3{CfpWWX}>Wek;`_gK0SYz2R56IMu)R zhAHNQ?^=2m|E z>|MF;P)k4Y)zaG!Bz4{#8|prddi6i>gY~c+0t$pN5QCwE+}Afea_`*WON#-oYmMFB z9p<6Lm+zmNe`8nnaex2MINZ{(YPi#oTNny}!B}Zu^@<^-uhg<1e8)xP3+cLHp&k-= zjgLB*I3Np8OX5;eZroQ-e;BHGDW1cf2HAQd>VGdvwK3!2R}9f;%rkd8F<_zNbnl%SHu7^bbL_Sra{^xdPo|TK)mOl+d`i)6H)zJLCsm@ z*#3WhP<0Yl{q+|KY%(tRIr8+6FHi@zdt`nKqw#}M-)5D%KZ+m?Nq z1})4$xEX{$=>TAW#;FcmF)W>`J~L2GfpBlXWuBq#u{*!9MH3l9uXn&CEyJGST?&wa z@T~*0J6lvQ3Qqd1(9U9_!7S-T9!jG}_{|YELoaRg5uXOo#l7ed7y~I7I*{rxop715$%*jY;lz!2pfCU(WpR=T$zgOVcN znAra+E9Ob71UsI_SFu-3zD7whhew2M02x@^nY6LLH>b~-EiqUne-lJ66YJ3Gz~Yru z&sDrx-;DUjH_5vfv-Uz^3}hEGGaewxCdF1i!)kehC02$aIk&X2WyP`7tpt^YSZ?P3 znG&Fhw+c6d1?~y}hKe-d(kli@Mbigv_qzG?TonbW)y7m_Jj#9_g4^)ePDm*Qbn_OA=T?OJLc?;2Ttaux)W|1+|q85lx1KY(Kjh8S65E#0;j;2AH z_ImCWvT%IC_g~PEV6_R2V4SnQIU^( z${3zR(;*F(kyWnfTas26OQNqmy7i@ZFHwIbA0Pvs^Q^Ys!?XC;{$dX?IrhjWkNR)g za?=p2+M20#CkXl>o`DYu0(u2wAO}Mo+svbOb*i+a1qVVVzUtr<2KE=PEP=|1y%LAf z9JIj#1@gV2nFJ&UlU%7Aq}#4|kTfPlha3=|jJ(>;V& z#fT3@b<9z0c}NXHmlmdO-eNM|9Yj}HZ#XaQxnwZ<5(_tjWmP=@hPL^8e^)HY4TJ^U z#I{Pn|Cl5s5r<~*`W{J){$uk{M#k?e9KYs(?r&JtGw|7O`B=_&vL8_6bY~ouqx3Yf zxQ2t3>wy){(10Q08KlD@pl}!iB^Y``k6ey$Z+m1V>fKIpA64b?hg`pm=r$$Mg%U|u zLYmn>X>cTln_>SHiT2-%l2>Y|+Ep4rz22IJ?4K&vZaqI4v)L6r>s9`;j$*N^am`N^ z`}c$v&@|wCm#hrX^jPW{^{o0>I$Nw)=hnT5HtULI*=fr)$vE+ zm&ID|`5|s+9ncu!@4iVsrGkK7!x*T+(1`(k>_eR%u6eV}=Z1}UYGs*-&LoHr%xH2x zel0!|6}n7AfHnLVa&7X$0WiE&$tAis0cgbMe4gWP0P3#c>417A4f1evX zMWzzBD;;-pCfrG$mv-iA+M_hyKB1xB`H1e(=wk--V7>6mK1vLVLg2}# z#BlqjTtVn1Llr+c+(ik;gOu*ydjrxZ@1mN+VoFsMxRR`>P0NH$I3*OknW906mTP`dzg@qtc@!AaFB8Z5aL+hU>^k z7yq53At5;{8Yw$ILHdP+)W7%rf1hDZIz&E(Qi?Ymc@FIr)26M*-_cH2Zk*WQfBE(% zvR`=$qpv(`B|wH+1qJo5qY6mkbgt<%h0CX=#j85bMHf5Zq&irB?0l#GZwx`yNa%IQ zNN4}Y|2rZ9l0K>sPz>yEefNLwU)^=s+B)BQ2~}SxO=ksHsoeIuJDoY~Xpe3E6J?6# z@}K-VBR$-I>+e?Y{>$H*^8fx@;~^tCaJp4q{gdZ2T#!NLaB?mZ28ryk#Z5dZYBJL& zrqOzEdMpR=m<9T9U?Fnv*+($ez(X3NgY@6|Ush3fzkR_>A`7i9&87M7OaI^g*8e{Y z4C?1m1`%8`gp0xd zsC<2A697X`Md#nGVs#~Qt3(osEg{pOXr+eqR$sRDg1406%|1&t|{*!ShW`|k~a5pCwfRT_dmNZLK-s*U;P zqiQlC&?WETAc!;fi6ttmK!y*A=3?Oyd7r|{OsAe#!HX)3>b?=uVf@Eru`gW+cGAU8 zACAOG#j+D>GfK@zXKV~%i(^Ut7=8Ajt?FGu@6(KgJS z$xec)-hude=#udl$1mbw3=CkX|LtL}n*&H=%tCCE&0VEVjbmvF4;(u`7ke+X9V7`} z&b+N`CsBr*p@!HS0K*xR;>s1nO!OEn>OdN{*>WQ0Al`F}@f$=%P31j87JGQx?<-?|pZn*)EKVWhkJ_jIm>iF1xfL4)r|C31BR9#POILOcW^7kZam@{$}hG9B*GY&!BCQ4 zqDK4aej902_q`GinyEqq=QlNU?uC)`NCu~7W&F8k=)Fq~cN%u^l>jg#i3t6Df0s*0 zuF#P2=B?~4W7pO|$8R~AzFfm=bo~5}(#Fewd13%$5E(r;7x>5?OF(wkCL-P!*&I%6 zL`JrLozhpoyzI_zLc}w?CxC#GU<@o5dz9`jcan-nE!?RDqd(nMb?>ZedqmZui1B9OO-n#<@b2BhQl~sLQ!+0 zkDgzz(FVxC&^I%&=}1dY3hlOinnoq{+AFUtve4=F1o4<93I%8n@eHkN5KuCVffWpm zw5K1r&cpTOt)}+lX10CquUG{dDTyi>U1qyoy{1)v*5JBio50Pm88r=nK^9rA|Ef1Q zgl`|-j!a(&;`^jx+X=~ zl24TK1{%9*U@}(L*eAp@^j-W?N`W!3fuUlSWDO^+3^?;9jqQV(Ra_~SCVja?^>1A0 z6yvH;eyd#ehCqYGMpZ0z8Z6SH;nSqE+kA|)gE2pxhWgSF zLwlIYfb%`|r%ML!Vfa6>HQ|>5V9>FpKe;MO`#VHYd8Cxm^GIe>X0Mbo+V=YNc;Y^9 z$l`ol=swy2dNgl^WO|TP7bO!(jrJPzIO9IXy@@YF4w_yfQJsARY9)1uXINH-fZoCw zI4_D4Qi+}OHsed0VE>`4A9t&ZSc;Ph$7I66l;GA!KUe*zNC1}zn| zzjx5t>z2Bn4e-51)nw>cf`scmYR-%-%LIKQc=AiQ>C65iz%<0AiJRBNRk}-it6^J= z@|Ik0`ekfd-~NO@WI2(crZ@rd3_C0k5ERD1b@6JCgUk5~b4=YjZ*ePuK`!e~WXjGk zPH5x_Xxjy5|G-TN#*&=ls(ZDxuf(0d~K#+J6#3q=8BP)m3vu~+PiY}_v5 zm8@pu7#NPTZht6<*WlU9Bi9~{k8lPlc=05U|lM6gT*ZZf7(toO5Lj^7bfnf_{<7MPkeN$rC_NuPpv2Fz{< zC=*zY zO67LQe;0pxzS&SAc6TP?Y7Lr5y|dEzTK-7jI(D3iR-IzusEHKNyCi7XwzAnTjyAm) zK8(!Xp>z0p>({;hCC|NRyTDXiMGiW|GZ5rMKv^&bUNE%#R)2+~1(Ax=s#(qJuKH@- za|WEFuUPIeN)f7i^!9%i`1o_eKgliqnhpSlRI`%5dz8eA?h_p8v9762>*tdXuc^~h zVEjxS6%uuQ9ue8K?*_C*kCo|`b&gAaz}NB%j~0@q9dZkGJG*a<&q{6&u3E~+* zVGvL@jDZgfWnBAi*|dzF5~%q+j$_#|K&gH#)=9n`_4vO2q^sD*>7U-1NPEK{*L z!yWzSt<^ogMmUZ4wYdkc0c1F)d;5gM#Zc_MSH~pb$6NCziw_`V)opZK0vwu7rx?SC zXJEV7mGKV7AOMEmK_Ylv520krKJ`4|P!+pYwz`Jl9P*L=owQ|%OvVVtWg6VVE8u3> zcIIIE_ug=xT9J9hQ1ruVqWuWkMLFMf-%Q~+FY9Fm``kyRKyvb^JyUEOpxXiZqu%V$ zse8+d8qD>}6lpcm_Ux2q+iEAP9yEKYjf!N}INx$gteu z4HjuguscrTiy?a%bo{ROsoFpPe2aE;>W7=*UV%FRh7G$Ywkw8*RK^cJ$i`kX)O=9$ zL0w+aL1%PpeswU3%k{+>RS<4Jz%&?}D5M6iMraS^)SNPOi0yYT#NVeNsV=ezV?He4TWuM=f7v|4hra|w6 zG~5i2*Bb#a#K``5d&N+nX|wX`M78;Z#S4?K9lCku!o|FP19QgWvwBPS$GB#I47jpJ zHFc^>!uwY2P8b8rC&96NjE=uHtP8t-U?_f^UPL^D3>pNK4`UDpLkn69L;KO{#@=)W zJ?E^!nL~Rc1i}i>9iII$ABEf;&3wr)PTdVRgB&*+^S>7*saEc=D+cWuUeV5s96vOD zKIbE0>v$f?(QUS>0@b&B$)6^6TG;?HJeN-1Zn^D2KzYAj9w%<;HN!OzrQ5oTn&*M| zzFnXLPQ){)Y(qc=Fa{AYv;xI?u+wsNY#G}Hyb|u%Wg9X7eZTy>294Oc3l9d)@g;+A zRRG)!fOvJyj#uv=f>J7x^{u%z+NnTf8&Ty$ll1lp~U&!DzY8PgDCOdi&6E8yl%i z;oxY5VbTT1F83%0@eH=55Ku9U;UO3r%_=lebV?h8 zqxX})&?hN`<26Ga@tL&<-T^Laq<4nPLgpyIC}Z;4k^+YuGB0(5L|-!-5Zxjw!< zmQ#!F0hUDkw`eKXR0ya9#_$LXHLMz|CKwEvC)m$8qi^!}|A?-ZKWPk7QZX#@EuIrg zzGSevrwTU%-8~xs3>t@z!(!S2dcP+vY zAOq5x2zQ@G*4_K)H}KnKEoF?)f*)mll9kDdmmyl|e2n-(+)}=;AfQqhgBTd6mW426%U3dcI*iks-xel zQAA%djO(|+&A`Zd1c1Tx7K+Uk18z^|+I}4Ngyo&5K9Pf;8$*}QIxAkjS4J%5M|9e`6xmV1Fx`SWFaGB8A5#Jjkts$Ut7=y&cJ;UD5 zITmeIx<+Q1R%aE~@4KPBR}2ZR z+<0ZGBd>EOEB(n2?|e6TL5spdr(?xaqXcoz_5*sQ=Wg)!r>^Wed6(XfmoMs2UYtF6 zOuSIzVv1hHH86Xwc!qd}L|q7|0><$8V#nT#Tc6KbzqIFacbQ-*S>u?+tqhA6w*`7D z4GzyqAGlmHBwE1VqPI0e0Wg?7Z-08lz~ztB;bNgW@}-jc6$wvtZYuIZ?&k;6Yu9&r=eMAeerg1#=y7>{`8%MDVU~iZgwcFr%H%wTY$L`HaFw-dh zhG-%kW4AxwR1sG&tLcB>ol=1~1XKlMkOD)m1x8TGw3pXds-HE`y~`qBD)4R1%thy9 zt#fBl&mzAXnk4iJ?xN(MMZ)&)Md^N7kHJ+MlD^ydG)La+2Q$s1vA$RRRR5$sHM~6l zQ<43~iJ(?jB0vVGKv#8A>Xc{a76Jte{bCp#4D`}yZ^-SiskxLas{}xZPebL!8`f$V zgESaAhyAJ<6LRdfj3vqk+5QcAE=+P}y;;Y&`G z)D^=Gh2gFJJ0W{v5)8|+x)pxWo6(!%&x4OgHOm+@p;$oAuujY5q1v1;F^;6lm56gN z_mgzIoh9C`z}AzF%wigO1Vuc<2Q~<(2F4(BafUUTbRm%}d(7|GDc9^mH?Qx0$=qig z(R*c%$L7Xpa+a42**@@(ms}>w1;S9mN`A#a>}7Z4oz58Hv>1lI$1xLN^=NYsTvn>% zWAPiuZ}Iv|fN2N`=vyIjT!=DFj4I#M!vf#iCfIsn8GNmM2W#E8f^`h>3>|kNpjsG% zEEvl6Q{Wb%^p5Sy=b66xmlix_npDNYJsH)YUFkWEhid|t4E2gBaHj!#dK&;k8TH$g zD~3X>L#8P(U3F`mNyPpgRPT@|6!}rkL5F7N`#QaRw}I|o{pe%rlYu=epShV_ns;ux zd-}j*VYZ&f`PTw3zi2Z>5aJmI$RVIQ7=s)bs-=(^oAhCnhV+c*Ig=iGF^--*CQZ|P z*P6G?_bK_RKbz{!w~FCrU@YKc|M%V?w!8B8e#4~SZhDjOGY5{>yM3Xf4z-rbW^T(! zO!EBwR3#=}3{L>2p`KOQ_vwh;=|>@)Z5lAPOn1`kPUpf`x3}6J21<_&#Szaiaj~+b z9>yRKh8E4}wZ8%dSp4J%Q9bvu)M3a8VXfpHWdD33l-T3SmV@X{5w?BdqyQA;r77tQs!&&w{)0{s^Kw8sS*Yk~Qz4Vf8+ z-iOp!vIrN95`$tgPYAloPqh-nAFP*}!-Ig{!x$96&;>{Ag^J+bB+jn2?<|{pao-a9 zeF6$IIKnE-LsMI$>@FExKl{PWplsR+fI&O}Iq8al)R@_eW<#Z&NpXz%lkx)ROr6o* z$p}}NHObS|rrTsn0Mn4QeNGd>x|g1#!9#)S+Hjirq~=qX3|cvxa5LyB-s1T8 zqBO_Z{`Xrnw;J^j_kzdT5cab+F-tVuxhTExwxB<-LppWX84A1gx;AXIRqy>P1yS*;?Dh>VuoypIs0_eRpgY6A!uw9U* z;tdr{7fqnb_eJj8_pAV9(8p!4YkMk+FME5oS&M<^L3EGrPG_1?lwMrUz3iyw|AFU* zlZzdDjW7mfFx2*SSciR?O4vBLw_E&NS?%2(UsDJD$8jX09mw5ajFw9Vzn}0QtalK3 z3xL5GllR3HLpVbct}nyq{&MuN7s33W>G%D|{AVYp?apt-t#`~pzyKMp-MZG?%b$w9 zGG1@Aulj>aJK?o%J12}3C5su(V_)y1Bi>4O;y{1Obynh z3JFF&+xc|fDA+Nat{-oukho-UON9Smy_?uF0ERs?-~20v;3ot%+z_v-rbALxS1b2{ z-ArUXRQI1;1QmKTD3Af5ySXuJm5E9ArthEL5b+BBcStzya5VGSojTGPZw4&< zPN#6_%jbfa-mz^J((o|lq3#5?j>L6{qk*g$Q(`oT)JBHDTF%> zuY;QaFfh!=1z#~Vxd_s^TIJO|cFZJ_bgi5Z60xNF*=158am`uyz3{v~z}~RCHpOE+ z(fhHyN!8W;VG2Ia;N9GplnFdHgr}4bzf+AMo`LZu1k?&+&;UcR7E7%Qc}<0-H*@uI z`}mDn2ik1ecIMANx2l4FH{PxNPj9I574U|eA+_`d*S{B~?>Q3_R}4&HefRbD=LCzm z)!9;8sN*zZYwUijx?)pp89J?X6dVI&C_+h?kZ4bIQq3O&wb#hKYI@}a?yfl7meQB%)nuZ0O zS#KRL)Z>@s!HR`SF^MyGwMx-U`K_K7GtA-Yu|@OZm;Nj4jrr%V^RQ21J%80){V!{abpRuhj_n@X4ikNPda6R_OXD( zzvN*H+W_JjBrc|WcEA|4!O*^I;U&ZnU!69dLr8@bYDZ?_4|D~)Gm}7y>eom~kHjw- zoO9>lW>_`)27tj|)AsN6bgj4sTB=um?$@U~@+%0uq`=B)HzOWj??&liFApt|1A5zM zU+YJIBhdzrm5&s&97j_BDkxqwP9Sl3b^$7+b{n#Zw9U-)=|A;HWw9W-Z|yTr%hq%)!loSHf`r-+Ke8C5FmX8ZzH9EfOEi z%w;U{#LdgTB9ma$;>;L4agh4@;9*SOW1w5b+~y?)EsKL@qLb-fXOVpA5LRCZ_{kMH zk0F01R7F#1dBwLC%vt`^f2>RUIPz#1RiU*Lk1QhKHY@$k}tPy^t>i zx&}9`4X+pH^jXdm3hlZzf6XE-+?p26T^J3u##K?e+F`CYRq zFAnm2scW(K79yha+(cYd@GaA|^MiHAS@N83muaY%z=oT_$FvRrgR=(P-}?=}yV~+3 zXWFaNy-YPDUgqKTL+Y)h6}uOt3dA(mm_{jfoPf3i&d*QMM;Y zelN5oEW}6OIR^0zmXZ)q4~#+g;(o(kFm`upwBaDu?`Qa;Jcp##QINcYcd2MiizHMd z53(*99F*Z7^48ji%>D00iMek3>?#eeuJZ!LdvCj@$M{JG-GzUcWpHSniv)8WXy>s@ zYaPF60FwmYUI5}5o?YC1>xD7sfuU(+ zRQJDQ64l3KCzq{iH5qu`4l!Ap3_VD%OLo1ny^vH%!(HfR5Si+0;H z%Yldqq69K7w-G#?SzW0pz%GAh-4rZ(quob=dkP?fM!+%!d+8Gzb;?qguL2vA+9S5l z64VMaBa=Ob1wM)(ek{GTmk|Wi2V>9&Lj{ga9Mtbb(A`CDt&cTm@Dwpw_;jLYuIBtw z0+sYdxz%NFxG#YWcTsY$jRwH*zE4BuDh-vgi5Wce)zxTj1@~E8?JHuD3Cs7L`$Cv4 zm6Vd+I0K!-nwm0r_Wj}6`-8ECT5-NfFSq^ef}?43Qlvv4_TjL2#Gl%e4se8k`e6(P z7Xv_#K6qygjysAFqB`pyz4?Y~A9Cy1I|Nnm9!uBsvHzdPH!$-t+ziV?QveuH$ENA7 z7@j^Klj@(|o7E{(4gc}_!^2mICqJpbMskV6|DTru!^esGvQ>L-O3j?kW^kns-(&fK-< zm8wz^E0#%H8gB>40LnG1px;zT;WFKwxjT)bdBGlNEEW+pYvb9^x6^L_t6U zFa{$qw9V5#hEi)TB+`v`PE=EdtdTW#Wa_A5=dw3w^gV=|;Xuz80E0@2 zL;MxP!JEDzg=K2;PRcy00PJ~xZ9E}mA~u%O(dZM*P0|vehbO&uaeW)KMI0#6E0k63 zjua9SjBh=SmQb$-y}dVb(ujpN8a-Z#B46(JNITCAP2CYQT+B(0MBj<^WORXuRvs(KHuMQ{WX=mGTOVzf42mF#HE(RI*M1Ff?6z z9&p7FR~Z_&JFYzY=;nsn^-7Jw6h?pkO-#ou+#W24rn+lDUuHDp8>?#`;V0m~$Chtg z^K(u0exRsedx!T^@5`PaGX4~ZXDID~fQDcUreNrHyW*32rie3WkTjMxuZKHIiJA)+mB>@(t5EZIx+ibGy z=ar2w7TNe_jBHXF8MuPQnj$>Wr)_O!5zo-_8v+`EF_?p)A!qk26K~_mU|su_fYQ(J zEgsnWD8|D=R|b2YTeRXp_>#d-3I6@7KL*DEFf@sg{#^>4{S908fk;bn1>#>H&ES9|hoZ3*w$C|W#mmW(2T#eO-4WXYT-OHuV*GFS?$!JP)= zG%CJ-FG|P4h8tIDkoTNPV3FqJ)V6RuXS^3NDY$vtE9D!`OV`n<&?Uz_Yk&-FK4M$n zPG8(G7SwoJV$u^H_~G^MgHU!m@o-9F;#_0IAFP)iy?D_*24k?iSo~>W@vATP5jl}l z_wv4n-juCi4R+{TZ;i?d8q`ila?DGHZ=u6*GcY<^0brp1ne_M7UVy_qhJtWoNjMRU zL}q3LJ2e)g4io;Jo`C%#qV*eJk^nMVGroJY2Fz!7=ISF z38eMmV*cyb*VU0hS{f$mu728kqw_Sd&XHyXcK%3d-! zp%cQ*V53qFfI(r5=I>GB$cfsbuh>deXvUnVkCsjg($^w;CU^qlSTpXbX&9S+0LUN_ z$;s$tC%6#S#H;T6K~O~MhAcs2Xb^A9E2SF&0}|GVFG|aL5YPmS!TRDOsBakLjVJhs z<$<{A&^uhOp{AIkjnS911r>7ymH;22UpDzb7+@bga6=vk9oO zB^V_?t84Eo&^g6#5kihJ84fX^7H&XC9+oC5VSOD<6^VI+W3%}wKQ?4n;H}HMf=?41 z5<~uL%Y%q#*ztsbCSeRVU}&CmhslisoH70LrZyexj=ra2qvcD;P9?O8_PQmZMirL~ zCU2PFW_ZLX!T;~Qp`drc;Ho#Y8fs=s>@LShSL~RqyIbn~>YeEo*SDwk0GqqLcwqtb zTlBNwul7tdlg%%QH@Q~=nm6t1ofq3N+8P=%D>PWLL=Zn~Px>$(0{Q}DumwX)WEd2X zV|3SX;xj!N)r4A{@M&3-AKgkOz8N~rk{x+@c(Mvf9{&BS6Exuf7)(*5maiDPYnPSQ zp0IQd2`28TjqTJpeK%*7=zu#{?#;ei1{#t=SRcj zVB!M_8$N&x1kpZy^pOhBN5wc_L`Vr^c`eEPAW_*=+fcI{1~YuZKs*E17z8v8W3UH9 zwSDz-7rUsCXgk&|CiHW`GMG3h7=gTW5@}7MN)wTh|0zmUgoIvjGnjHx3jBLfVrEbO z`%5Wyi4`-_=aV5p_c!zORVph?p0_)xBm=wg32bB$$5 zf@PE$o!J_l|Aa+J!DRq#d>Zi#gcpx*UttUmU}y@>NhH6ndgq)#@Jy2BqXM{m(Tq;ON3DhnUm2! zSR>c=`iJR9!$Sbmupjq+q-unmkGHnFNeLp97)Z17+5bW8>(9cw1rXbB{kxmFq%8*fnHCy)Wl1FLD)4uCmr%0 zv`xBcco?XV#;m|;g5l#RLZ^%P(IqnXgdw0=7{fC#)O2ddb!Dk>EY9B}E|P4>S<`v@ zOVFLdC^V&+PDlH16qjk3ZAwS>xc(+|6M0dog^g6N@)+ zakqD|;M*+~uJDi_K<`Con0Tvp+-LGPi1C)GONQ1ieR~UL%(erU+*58zs@Fk5d>S|m zA)s$C1}89-!Rq!(!1|YJZPKZ+(a83uH=OF(Mh^CzoIg2bYJU&@x%>9U{vF(Dz-bNRDL46Fg-~bxu4WuH}glb^Ee6JVV-on}H;dQt01{Qdm!z;uV9QSv`l|I=}6? zydlrC1%m7LW&V_kuLTc;FrN*+8ed8SmlJ0R6E36@&1wE`engmh;13>%WO^6q%PruF-hshxU)%sy*^khjDDL?nV2H0tLG~;iy|}6fSzGpeHY6#zP5IfTKV`<**BV(>8eF40->!f zLs-V3{^@GO?~9hPxHvqy1Y__3LqVo7A|6Bdg)wy7SYsQ%rm8qX(w|}buB$I(+{)K4 zQTh)Yb4_^K8VY!O;%_T81%rf}u*g z_A{?`78C3^WHBcAFSgi~wpQfTrN%auM-_=1ODJ5X!SCJ)+zhz49t;0_Z)h7*alT?` zpE1-Bmp>U2QX|aDGp!;r_D-^BSxvZp|rG>Kk9VdC8F3WDYk&BGv=|22Gaf!>crW znQ~v04{M$pT;KNP%3C(bwJ66{?%!N@-K>fE$!Q04L+WYFP;e}6-EJhjNb7bOL<##?=^oWv6azJ5 z>$A@&l>paVw^*ViN2k4*PQA(YTF{7;myVN^mQ16 z4;adYP4EqwIve9F=h};DS#pGT0D#^1i(<$75MjCw9x0Tp^txR+y6>VY&8{{3Ijh-$BU>c|`DevsBzYw9&Z5X+R zcdTpUG_a-r+w~Z$t9%4^*^dkH45b%e-?m^3;EVkYV9XV9rp`$lJ<3rTa5}yCQ=%kVwro4QyO$nH4{GpWVn3~Y1T&s-_y?Z zrGA?8V~6v1OO=&_27WpX7w@dB#61zu(0VZ(dI!dEF_4SEVpV3dLE<6(`$z%WpF47r z-eklqNeu4Jn;F`}LGzcxp{r=a)8S?yNuL71AWtdXcg3JA%TCl_V3W;J+48 zq-7GML_aUu5Zj?cT~`N?0jKQ7_08eBRcI^HdeWK*fy?gjgS!*O9~j9Ui?MEEn{Tg)szxq1>VM?W}V~(=>|QY0O#prNNz8^){tsv4x`=4I3TD@l^LysfPTOj0>Mz$6p1uFDKxd;ZMAep zghRH5)Jg1Ixv5@CefIC8rsU!-8Qu%Q&mbl40Dyt=Ys=pWGD|Gn3Aheyd<^|%>d87h zeha}G(kt(83KLj5Dc9&lrUOjFr`arX9(!}_3Ka~asm*6f0mc|1)6euIk%*v) z5TAybEeL22#_;0eDSGoadA5jPvKHM}sVV^@DxUcFQs~w(#;Ho2Cnue{hL;SXCUtP9 zfrq9J0E3~T!unMjKG863q00X*B|c^y6q`fuQs=4Wj{1sibR0oisc>|66(GYS1Ein~ zKl-@V2-*8gW+7#0bgHzkMRI4iGYj=nAo}!(XINo`fPTUlg22$bP*$3JB5ja2^1>EY zsSR4&{FourR$a?z+vBp3hs{No3@@kc;AYUry!P&05v=3tl217@s>wF56D9pu8?k7<^Eb(d_a2fz>+C$E0R(Eeh)WaHM?_mkJ3Vm#IV899M#g3lml5t<~pW_Tx!9cXXxvB=F8 zBs(Kdy0cq>$%9jTU8r-@u%0Sa{-v0C)t3^)k4l$0%7TD?!5Bg=ic)&o^$e5yk-&e=#PU}h0EV)CzrS->i7f7|3sRn<*%3{h zU6=3{H00)Gdfl?T`xNQc1G8V5KyUjHc$00_<9_(`q;1ArXltftVUSKYVXi-^*H>*T zsVUGG;c1Y)_8kKH4PyueLrax20&r+o+GWy|O}WOOr!R&*T}uuPUl+*B>sb-@|1;Lg zX#)PDBzN=;00XJW!@pAkm`-H;yui#H9Lr_dl*IcRO|BY(E?9~SDWogms*p)ufJNyc z^OLfW@zUi*HI6oYUekg;l9n`f28nz}AzfvGX{JELGvLrdKnE~}mtd%)bv4ltaqlbR z^lmmEKgqXU5|Oy!K5wQ{V+YKnroI2{1odljg1ac$-(Y_9@4eyvg5a~OqNL8pKUK<5 zs6MLoWPG>L9`f>*)oa_kdg(N^{tr@zS%E$`;CDUUj<&_krwB;vulCNpADkvWqmXRcK{D0L=Yug_!%Tas2M4Qm- z0GNigZbIyFWz~}#?>+BmSV;woWvdsPYwYrMn`zJQ8W*G?o`Et40y=^*gn^;oWUEf` zaqKwsMkG{nJZ_ffp1$lfQMQ)(_DUZjTK03|vNu>w62Z;jA<_hZAtQ1@?}}j(EAwX} zi@ohkl<4&g-A!aF97~#$Zmbc~5U5xw=Smwu25CV~v9SCf=1z-6L;F}QZfSRY-e}JK zb|7_V4C<|Z{Q~g}466{(F^nM`42|>dCMTlk6Ge+tSmCkg(g}F=U=3eWYEbUA1)k}z zw|}Mtc!O5qW-v0x5c~I{)Z;K$bj6_1Xgp@KX6q8(tYgzc{iI{a&GuQea*oB0kZz9V zs96g@25zlgr08iMR+14*a&-k;5!bw1b(UzIDTkZW6k^!h6^Lixx>&Jv0%M2(Lq)7@ zl5FfOZ{c4y`FCn{Qgcw@B@R$pHYCg^O44M z)aL!r@k<8t+whOWy*82xfFZ7nbmb}y;H?hd5a&L>_~>qKew5Jx*Yq{qa3WDFh^kNi zeloEJK!*3ff*(s$VapFG71JjZ;tQ+{Smrgw4V<|I^Ta7^;v@;6D=3NU{Qe0X#(Zy_PZ{$A($Ur-`d3**|R4H)zEC|wKJq{vM zsG^@&B|FrEM3Ws_cOafY@frkl4r7SAxPl0M7Au@=Y^sXiBJi=GOqC5}k~hFkW!i0PxO+phIhXjq_lAvOe*Pw%Ncx5A zilHuQ-7)i)p5_PzA4bf#aR0k)m_xt)s!sddOC8Uj1{VWl_*rkDJk;1ZxbW+p5v{wH z6N%I)`O$YJ!2@B7Se=m`#BVc^HH?FhBf}VCz|hy9==6T7_H3kt9_XWl%aYs3)hK+H zX{QDc5h=dJlJ>gn4K3Kla5H35bOK-y#<~-G#c=z6Vfg6h4NuR0Wa~6^4yUPGWiK&g z?Ie+&FYGW#vF8C~pcX)W+aIuYy8CP`h~UV@2e-WtY>vsj;z*PJztpvU*8{?8MOWagiR%Bzo{`sL2H;tr3xi1+USo7g#coBjp@$W^c zv7>zYiebt{_{9b$hK&d9ZIj7po(a_-`B8SL+}}qIt*rn-9=yltUO=AS%+C2; zFd8|5QeighqxLuLEt7kf3=LuMk4mpR)&aoK+x(sCiowVBC|N8>y`pT4hSVkI*ows` z@g+w_JMD+xj9MShby)y1VERmV z_koaKhcU!~p~fnaFGVwckNdtT7DQIy3Ro|Hzw)G=n7zL|O#Bn?le|lY+-)DY)4=JG z1Au{Hg!S(aR>+yigoIxj0-3S3q|Z>#SJWDC69+pQVk%(b(5v=2#;QU zq=pKCkQ<_p^@vaAeiSe{h;84K{XJ_tD~j3FKjeObSlxc$CACsERlkcHnQ z0!NF9SaoAuIHjO3=&@g;-zCHGyDGRDPEU6LFr>APk6fiedSgcD-pgA29Q~~41ijZl z6l?mF8j8st{11Pm+^#zY`VsUNy13%IW3FfMPE=WMEE~RPhJkM1k4JtS^1o=i>$j-d zs1NjXNl2qGASEq`NC=96BHf+Rh_rMLLnEOGQUW85NJzIdNC-%`fOJTwz~Or5!8t#i z>%5nH=6$Z`FW}>M-Lv;z_gWQYYhN%q{|{d6MbSV&Sa61TFm%9J20e`SfukLZhfo2H zZ|J>bk5q` z5SORc9`&PA?3wrupInXYET@3J+EXx9r4k^0bNH|6<55#Oy?^8*!^Fj+-T;iW_vgVCc% zgc*XEg8(par?VShF;u_fE~&F3Q=n{(WXtD1OAM|sX!gIg5a6IR(_}Su2p>eT{}VYz-a2|DT|CiM&uWzj|~tI4xAwo4E?xMoYvO;FuRwg zm1Zi%dm z2m%s9m26wR(B$7~3U%pEZ?lO|0c|Dz{XRR@68?Em&f z=Pl|W%%I~)E&1<7sXnkS=Zc}A7u|1UX3r>@ouR4h&i$;L1~TJ(qYWHue%a_&rhF;@ z)9^E!M1EICqp0q4|MF~ZIUz@Yu6yCoIHAyK$#yPHq!jYgQ2GJ_!h07Ekp{1#== zOmi?%jaxg{&W`Yf9=1;z?q6s6#CIN2?K%i6N}+%F5oTzy4Sf6$9G2rPXkf z+FOm9M4QrGj9V^(_-XVg=g0SW;)t&&=YImozyRu`UYPK*JVu>O=G7taE4?sR4;7s91lx3tp0qbJM#OPJfB8R+b)iD*v~^LNqyn0 zVi?1_d-Di0KzX+9NwH|GwbeuBTirZ^B^pGfsp_@0tWc-q-6;ewpS-*K%fqaqg#pPAAx)$~I$DnjRfvj0 zU<{^qJ_x4)%S-avzn=}Z8P|rc(oiqblkV+^aqGFr7>-MyLzV%mSrVhi^_>qd@Rh}& zSvvq3eo|{F&DfYF*&dQxx!WpL$SD1E*QgWZp805d{=)9fZ@5a{@)+0>liU{ zxag#w^?v6Zzp`ixqbM9?jmbGUX`VCp(of!b29N>EyN6R~IUzcVq;jIe_xPR65zT!1 zb@`{Ds1Y;GV|S1t$S8Xsff6T&2Ox(`6vJp1!>;T79puTq~NV(-F+JRPU0=q|l6i zPx}}kgKOZ3LQ|&vl!DeHg1ljZlH&zQ!h|u@pTCnRI4a^Shmp^)?h653hcl#sp(K(r zQ>?ak8sl0Jg3`{OfKX@{U9Hl1&JT9U<&ZPk|fGcd z#bQQzqS)dnzFHAUKt99%Bm_hZXGjM_>p9+;qVcaiB3#B3e-Vc#cC_tqE6R(Q-f)Ob zT0SK>2F6fqgLqMrqjm(q;4*LU?kWv64<$c!n||MW8(yfKIMwv&&FQz~yL0{7VJ!pf z8JZGn02#L8C_EFdvszJTuj^0s+z7xFReT)GhbBAfJG5zkTa_633>Oa|AQCu31{nIC z)KsndyU9HAe@Gvn{@yfbSqrTuNdqO zO^4nPyT~Su zyn|RF|$x+7RUQs`gc&^^ycn!y2nD$Xwrj)No?Gf%wQNpop}$!3^(qp0$`BzZS%Wg z=pefF{iMV?>wVOVT>(YgZdsGzHcm8b!6^4Ap#k^jKsz(k!)l$LemW#UyKU0IV(@t- zfl2wS3YV8@biU{Avz}b!U%HZ|)`Nh^;SAYeXy}GpjzQi7+5jc#Bl8JTij-m9I$v7G z&)+N6uJ6<9wZa${X1*iL;H;DafFW<~eaIC9`in%?zG@-en>#j6(D?8?^eAbwO*y-9VDlP7=_kn&VFKc}M(HANr01KP+7E0eyfmOlKj!FIqF5Pv+mxhN)$%zoXKhHYVsDZ=G=Kw?Ezcs?@aF@OYLi zGW>n3fg83V?c=+O0MkHfCS4oWtAkUVn=-PYXpP0tSG^ad8lM|AM=+1_dA1Mv3<4n# z5EY!^(`9EyG1eWBDZX2bu*AMxRbUavlf4x$*>As&cqE}B*H?P~OM~VG!fBWp_XWTp z{7^0WDh(}Oe2K~vs7WnzPMXpn>!5;Yxk2fKp8*qj^FtkyCtf4vAQbt#!?ctMKB1-z& z=y#_Ey3~Hv#6I;I?D%ggvF0M;MX86n3jhPPiRj}i28Go9sM2=!!|(MX@9CG`&(3=( zy-pO8+(326`xARR8R!}f-2!=0R&XRkLSOBOaXzHED8@R#jdtbH=SU(G)~&h<=i%%I&2JLyMLZ__v;uaBUujUQ(3!O~DT?1yj~7|khU z|Gg;jJ^TcBTR%P|f)ch}q4C z%%&JJzuqn{vDOR-Jn+6x)wV>?D!jm9X@Wl z-XeD6G?r9q)@GmH4f@gwAVYzsrzm8Sq(k28bMCD5=ekYFP4bEhb1ak=r2zW|>H_35 z=(9mUG;oH3%K@Mz6^olwVGWPyGY1?+$x_<}B7WdJvY4rRFn5YgHS*uR=x9|cgc+_; z<^y1$Aa8hcl?K`0BQXc%R(F^vjO1TWKf3?&=1S0kb}t5bJ6j@|kL(yg2HFh?MY;Do zPtL^uG?VMrS?!^?xM*WqqpY9T2+lGE`ILaFD9cv$67g-g8O#T z-r+W9MeZ8j%XzLZJ112BXmWk~N6d$zI1~ZoGq_)VeWQaje7WrCcBFmNUX_kkc3fTE zD7j>m7EeeowjcNjBjj3%w%^xu7=x*gJi-hF7Eu5gitDH>uNcBT$gy_7nD~nBYu)vc zzF~B^W{(x$vstc&(eiK)=F9>tN}k?+R0$$|A>i_Pt)IJs;ycXiK8X_qH_$)RXXV*i7`}|=R&~~wxBBEt` zEWNj!yI(T9Ut41o8{6o5J#(5?9OT2K=ymrY@)^SAAs~7zFhcp|GjnkXs|a=;eTn^ibI$|z~#35zZa#6{qVn^eK3zoMmk)Wzq3;e z>AmWu%ZUi-2(+tzX4@xbSLA<_GzefC#Gc#@rNQ`U!Y|o)1J6$bWiS4rf&F&iruUQQ z{)`NT$X`Y&8(R+nF~Av0!O&+HGBFC1Y(vBoG3=RwUVKJmM{EsSG1zTt&%3Q01-f7i z&UM8IGwfe;1i-+3(58HqhAxyH@|nCHvq|TQ;dT*v{NI#e6>oU%Qwto{y#6H;40K|> zWqOP9FXpA+$HJe72IhZ1Op06{2Mf=FH<@mH9+4$R{=R70R2~S35zbI{`Gyta?v7OD zmSsWo`RZ*YuQ3{dU;Xx~ZYPZ?9PD}8PU9cg)aoC|pGquSOa%ck!x<{TP@C97 zrJIF}Et0I)(+anI+z2V02EJj6ics|2x%_vC@!yny{b3Y@8Gd4_17M)llEu4XAZDbS zA})`U2_PI zm2x$P4S6dAwISY0Y}*J0z_6CiiGRg#LR-}H;L{x(seRM@N958X%=+ufUDMy94J)^E z7S%2E0j8m+WY>RBi1U71rc1fN1A~l&K7nMZjYix`jx{@mmT+<8GqhqtKrC>EDll|P zy^n7`=p#r5#ANV;e{?APmTs3w-A@g@N%!mLod@Xh$x)3)TWBDa>zf~~nX1-?B zOJ=b+@6UW{EmAd^{>W$eetGwe70yt7`S_OJ{ej{|jG_NC1)`Ago!1j{+R-;UxA-Ro z#F_U4JZoVLKF|0NE=pT!f{OosHe}V@CA?yA8Ts5tR=$31PiY*dO$Do~L?r7+v-7D) zIn#_7tJDfPKnAZN>D-gb_J9NZ5hrf+H_JvmFYg-{*_paqG3>Sxts#GAhU~}z1jGhs zsJR@6YfZY|%toNt^CPI!eF_Avjyn)3UI^&a^(%-G`q|v`KMZ9&b%?KKUE~Y^z@Y8U zTz18Pb|5Gij-S4w%(7BseKIohyi(6AO(vXenMHv^02c-5H4_~DTUB$!Tchh4qWW*?DsLfB7 z?7P+LRLnOp_%Q*d;eL4$-w3%`_2Sf1r;tbq#W#c%qtDYb-yUb^GU$$2e?mUP>N*6( z0cWVY+zDDqQal}WGk^?plgd5Onks_tLBo>}SHFRFA$QWyW7z1DQd7btgc-z-sg?e{ zD1|aT{X2P5Lmfr>#p<`DADX-xU0h9fG;YqDfsChfW7s8^)KyoX0Az@dwBn97#_411TieK_F^^_M$AX;UzAy9UXWEM6NEN#77J z4jV;{pRF%j*OhbqwJuZq$}_s7&P^z#|s0v~X*eNLXr z6}}lJHF@{(R+f19lVHb(02z$dnk^Wr%Lkmf-yY3B*k(*-R!mPToV7%^^<{8jU0g;! z!`Tu9#06*g3Wn}PQpRqaOy%88C?aSU=~>nC-A9wAEKTq&iuCBAv1o@el&FX!oQCMN z5&#UZu@(L{*5kMP3H&y`c-^y+`9@^B7en!}hcR#LqI`C%#O*=?H84PiVaVDDa{y~s zj4Tb#ve>SF?yq#KpuEc1VJnkQLbqzdkj@~7Z4Lq5fipB*KE7eTB{(7_roI=O6&Nw{ z^L3b@Hi|l`8{L@r%xz-2`wTFKwtB=bT^;RQ0ASe9Dc8M912t8I;_HW6g^lk;>Ttnu}=DVtZbMgKiTR}G~j zoQ7$1Ipu#p8$43kCjK(4|CAh;P=DKZ?Rx)GR|wivl1yccIB2TKqmxehVeNf@3>M%) zo>3WGC6q4n_pjMJC(PAIH}zSIiXf7{1w{G!CT1_9lLGc<#tQcicJy_8E)9Z#+Nm>)5ORQ^yiAtLX=`AJ?|%M4X2g)u}! z3K3?wEB*@rgFgT6_bY}0Bfk81ADOuHxqrO>GaZT;Znrh#VR>huYr6xi*-aUvR9`L%qKdMNkMxDl=0>!VWsQgu z)v$^a8L=RrfqxGIx(8=y1w&hU4~N~b{kIZI!?$K$y`yFfNOj8pBYh+M3ZmEd!W_ z%8AXN!BUG0a%tFwHuvNY8pOEq6O>agl+$(+`JcYhMLxr04+w}4&d_$*nGsmhiPmP} zt*aN2-d5H5B6FANx{D3||TV43(S8QXEgkw!)CsDS1B(K_=srdFEd~1jjUk901*ZxX<^2Ek|JFl)IT}zT!>UHH`b9yN&bZPeq&R`$WFZ{;eB#AGX;+V1MhSYlx4Dxqg>i z_1`N`BN!rb^-rEw-JO7ZZ`wHisCm5i+sTWJleyk_?=!4E+u_ve5lWypt9&@ViIgZP z8PAl-D%?IUCp8X~7(bUjE2mp@*>{yGwEW-x*8hJPxb**D463goAbvPQ2N)XhPEJxT zf+YUUd@)^*wvDZ9%V71jRZ)UY4ws-(QlE1egT@cUcV#367y)3I^v`L%V({YWfEdoW^;F7a6SY2-7QLm?nRI725Gx~sM% zJG?$ROyDj->ZFa0_v04xSgObyTYA(T0TSmGVptk1KxqgwC`p|FU^tC3_&bPuQ2g0c z1kERk1(W%qakQvLpXTr61n=fN_8$GD_pKN@0?4pck=)P4e7+(3*ostio;}KouE9oS z)_P`pLM!pQ6bteP>dD!2LO?=rhAuGF{}HW*Yf!~c38}Lm>3Wm(S$Q{7jSK~%6R{hJ z`-nmv{$sGehcJUzrKH-wpABUG8GomIK0MHSDt1J1^vSa84Y8|7!7x1o|C!9E;ft=# zqKHjDpreN`u9e%L%ZReQyO9&?mPGf*<}>$ukEB?q%+(Dne&Uuo=)Iznr3?{)~0ae(RORt1qy2hF$?U1e)adv!iv)ET@i#C_<7#}VBn2HFT5&B zjnG&~XdKkw;rfVN<+t=fg*;nVkiJ)T=$GP__GdjT0MkGXQWdXUG~&b6;uKFF`lAf` z9TR3}?dKK9$x1}=>aiX28T_RoAYnK|4;X6BP;NTjQi<~_bHIYUlPDgqq~BRUBLA4N z>0ao2{bm|i8oZ(rKcaohW&kiWKf;W>V#vcNb9&)JginzB+{2BiJT(&35=8bnY0mPZ zR&ulh@O4kVl=+-t-C6!*7I#q7*v-!_hu`jYE%KarKB^)6AcZrDe1`Bb2uK9Z@cr`J z&cvO*UYA!-Kfl)IEk`&FTH>7Q|6Y`?pV$8F z2_xMo%-ef8-4nSJ!R|#IpFr)~WxlHI2%foV`Ebkw8|V?eH1(twbAqcz1$1+yDp5qE z1)q>5s{an5ZpERI;pRN@+qUK2TR}h%;S9ZCD1}x@j08=$c|lO3&pVy_B6YalDzw6@ zsx9$UEZkK_zhDe)+xHP>Xc~0`!0^~SGw&)5L!l-uYj2qc-w=2@=kScGn}ol80m>fM ze@ZV#tC70)&(RAs%HSZ)7dN@u&;0b3c=aiepN7;w5YQty zLmwDA%2Dm&Si*?)9gmIQWL&wSERQZ=ld>ZbO>@xpq}t&W#*it5_*nXSw^jfQ&74g% zR}2+j80yf9!+zt7*N1)t)nss$eX!C-ZKQPE30k}HV#OHX*#O$zip2>y#SfD4n!A_S z&)fPE`@I64N*0$q+O@ZW(_6@A$c=)4MBxnmmwS{lvtCa#zcBeQTk*U;)z_utIj)cE z+IaQH_xcZqqe+Bd46fk=2&X}wfkflqi;|mzu-O#@Zxb`iaedYeZq#3sCE4|)npsQ! z3ZPE}6++Kvl*OOY0%S0CW@5jwPkRgN0qe7PjKfuCDA?C3yYYmA>O`hEsa*^C3?)nu z&|^5m4=~i7!y*$$xTv7Bh9=P_14EgX=7DNHh$A%Pwc$HLpY8xT4dn{!7jA2yq(FT^YgR5B=X!2pNCu znO@9~`&W1Xz?>)RsuGygEF-7l^Owlb&q+y zLX8H%pz&_$=!zj}P+7ZBwO2R!r+u5eSZhp7gcxlz+1~fKC*qZ>fI&9O8BV?M052>|xcCEXM_$2nxb#WQS5MCXOFayTIGyn!k%+`-r4D{F-LdWMJpWQO#nSUl<1XcR_s^eYjASn~<@iMTST#~yXIun`& z^3$+h1p!II8AicSxyC)4!Kin1Zex!EV{9@@f4Y6NEFvZC^DGZ=MeTOzhB3s5BL3N@ zuAf8e--}Xv^dqM$hOX<_U6^Z=1!lj!-y1wbbLFNcV?pO{%%yJ6;m-3ap_|{0E)6wyOIcg`* zvL5moE-t_OOTih&!B9%aL(SFE^0Bjx9fpN)R~jD)>#gvY5)nuCxOkr?v_$@6cy$Zm zqJ-Vi3V=Z{TO5?z2^92PIR0X=pdYY}^p^-j?S+;&)|#-fXmi$5P1uembtd zhq``p5&6wX@}ztakPMt*@^V_w5Xy>j;O}{#rtzRisJNNwZEy~FIHYj;_Org$j_P|b zhLR@4pQ6A2G6cX7EmRbIRg}D?Vr4sL%nP~N=nkL9Mhwm85yw8LxFrcK7!=zVuLOF} zP*8mvHQvd2e{(D>sTy>mgTu<}v6Zti*NA3g$mZtIg!G~$PcsYw$-)_?z)5eqT_deL3t;!m3!KlvsY;*9`>4jj*p16 zb?Wv0Jr^aGgnWkE?hue1oMHNMykxIYdh}8Y?nO3z&B*4BXD4{+Q)y?3Gn$kgVfCcn zykHFe4weWrfLKoeFpPEX{vDc>@ZDV9zzC`ug&t+*v|YV)N1DYYluO}t5rM(D`iK_L zkD#dv_S4dgT%^=wCE#zyA=z6MpL$o+cwEK@chC~WtB~IyBhPdB+#nBUm;pl{;K>h! zvxXV4u33C{Okh-148Xrmyn)8LSL8LZ8|ZxqV{pPDMwsD&)-#=dKO2bDBW_=%fj9K) zPX$SBbVdX9OqKg|AibjjBS%nSwM(kQX5W25pm#|!w(gejJgFo5L!Mlbv_<3?Qv)?< z`bv^!Ycn%VSDLzt{4@wPLqG~}hM!=lGnIJVLK$j6HMskR>x=M#o^BM;yPjxajn#O? z-*(hYU<_{3h(Eray^R6D(99dwd&NLH*D3xXwC8#N^{!u=-R|UixNGkZds96D~BZRs8r^SehvLY*2LD%rAH&L{m{$L3z5IFL|)?Z>zg8+VfONf zetgRJCsmvk6epngh9FagkHxwDvsztD*HK1=XzEc8jG;Um@s}AEL$d%F5-^zl&L^P+ zJ$3t?8+Y${kd%mSs*-loPV>W|TK~EF>$(!>pZ@p*WcW52d#5E}u&a}G&2_WGQ$F{W z+Zlh@jjAMVN4E^nFb?w5AWs4TDZv@$z)+c?VYiOr;o_>z0)0sUy2zV`L^`w^fEXK}B>V z>T3_53>m-X1;`*;!!bhOskDYQwV=`J!9+ALhvz)&I7+S70F9W)L-{`_N*Xl~kTRTM z9t=%jiP+(h%iz{swLW?kZ1qH}ukuL=M(9jlH4RHg;4kw3NkiGa<0l9+@VR>dV0dp9 z_qQ`cLD}N`0e#+lKqb|2hG3W?{`*JW(N13S=uS?{*qnVp*WkAK)5m5Wl^;9I%YL(! zA99nzr?cQxW z>i1u?-u4@tcTxTF-&p!k7Bqwz62`s(V0bbd`S+btT##c-SE1%TEV;#C*mkuoOnVCI~&y75Wmv%NrF=E z--{Cc7i#*eqNH0kzOAjfIol8sbVChSJl3>r7=tRwhvN*jGk+HEF%%%f?F(&OJAAz( zB{tmac>LN{KOAtMeDl^7ICC~-!d=>P< zXSGhfste@EWlO4b3B}(DvH@gZu0yZO;}DHo5#~A%$!CiZ`MP;C3RfyL_r1#t|J^8M z^|ySAB_$j5W-CM(IFwabfge>P=V@_KVQ0e^dc=3^ z4e}KOU=S(!bN7m2jUM`et5RZTqex9^g^`T0{FRQ|MmjD{5iQMWrYNN$K!zISqthU6 z*$9UT?b3>%Akih9^rw0Fb66C=eqB(!JBvX+LohW2qycAG21BcV8Tx1q-W`*4Mjy1N z!!qD}{O2@^O14Y>hE(@r1K%AOL%_FEgwKZGH5ULFZew=+?dYyUi)C(?ylqeDK0+F( z6iAN}--}`*Bj#VPcvxR6#Pu5>gWC|E?nZ=0^%JXGJF&-@`P^j>nF>vOh|cBNWMBAU z&m*7VO&0{D31?UVLu)p#huG#BOrd<2NgcUy-($Kc!fp-gs5S7+kLNXm&3_%;t~Oo> zGgQmT>;L=N@XML{@5_vPCNV*KCb1`slpp-LLJFA|Vq!LNl)(Pq#ws&)RHGdLGJvd# z-_Wc}jD5Xd%k1V&=%S^zaAGa|^TyeAF>%X~ujj~TNW2`Hqy=YK1w*-V4TrjulII-` zEe@bRzSYVt`$eB^$?xAlJ3e=J>EAt7~QwuW+pUu zZgZ2)a3h}~<8r*DHk@JYavQO2?}

    X}EWQWZdpyA=*F$-L8@iWsitB_jTy7;eVrt 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