diff --git a/SECURITY.md b/SECURITY.md index 1c99ab59505a..0b497b44aece 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -29,147 +29,69 @@ Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A` ``` -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: SKS 1.1.6 -Comment: Hostname: pgp.mit.edu -mQINBFgl3tgBEAC8A1tUBkD9YV+eLrOmtgy+/JS/H9RoZvkg3K1WZ8IYfj6iIRaYneAk3Bp1 -82GUPVz/zhKr2g0tMXIScDR3EnaDsY+Qg+JqQl8NOG+Cikr1nnkG2on9L8c8yiqry1ZTCmYM -qCa2acTFqnyuXJ482aZNtB4QG2BpzfhW4k8YThpegk/EoRUim+y7buJDtoNf7YILlhDQXN8q -lHB02DWOVUihph9tUIFsPK6BvTr9SIr/eG6j6k0bfUo9pexOn7LS4SojoJmsm/5dp6AoKlac -48cZU5zwR9AYcq/nvkrfmf2WkObg/xRdEvKZzn05jRopmAIwmoC3CiLmqCHPmT5a29vEob/y -PFE335k+ujjZCPOu7OwjzDk7M0zMSfnNfDq8bXh16nn+ueBxJ0NzgD1oC6c2PhM+XRQCXCho -yI8vbfp4dGvCvYqvQAE1bWjqnumZ/7vUPgZN6gDfiAzG2mUxC2SeFBhacgzDvtQls+uuvm+F -nQOUgg2Hh8x2zgoZ7kqV29wjaUPFREuew7e+Th5BxielnzOfVycVXeSuvvIn6cd3g/s8mX1c -2kLSXJR7+KdWDrIrR5Az0kwAqFZt6B6QTlDrPswu3mxsm5TzMbny0PsbL/HBM+GZEZCjMXxB -8bqV2eSaktjnSlUNX1VXxyOxXA+ZG2jwpr51egi57riVRXokrQARAQABtDRFdGhlcmV1bSBG -b3VuZGF0aW9uIEJ1ZyBCb3VudHkgPGJvdW50eUBldGhlcmV1bS5vcmc+iQIcBBEBCAAGBQJa -FCY6AAoJEHoMA3Q0/nfveH8P+gJBPo9BXZL8isUfbUWjwLi81Yi70hZqIJUnz64SWTqBzg5b -mCZ69Ji5637THsxQetS2ARabz0DybQ779FhD/IWnqV9T3KuBM/9RzJtuhLzKCyMrAINPMo28 -rKWdunHHarpuR4m3tL2zWJkle5QVYb+vkZXJJE98PJw+N4IYeKKeCs2ubeqZu636GA0sMzzB -Jn3m/dRRA2va+/zzbr6F6b51ynzbMxWKTsJnstjC8gs8EeI+Zcd6otSyelLtCUkk3h5sTvpV -Wv67BNSU0BYsMkxyFi9PUyy07Wixgeas89K5jG1oOtDva/FkpRHrTE/WA5OXDRcLrHJM+SwD -CwqcLQqJd09NxwUW1iKeBmPptTiOGu1Gv2o7aEyoaWrHRBO7JuYrQrj6q2B3H1Je0zjAd2qt -09ni2bLwLn4LA+VDpprNTO+eZDprv09s2oFSU6NwziHybovu0y7X4pADGkK2evOM7c86PohX -QRQ1M1T16xLj6wP8/Ykwl6v/LUk7iDPXP3GPILnh4YOkwBR3DsCOPn8098xy7FxEELmupRzt -Cj9oC7YAoweeShgUjBPzb+nGY1m6OcFfbUPBgFyMMfwF6joHbiVIO+39+Ut2g2ysZa7KF+yp -XqVDqyEkYXsOLb25OC7brt8IJEPgBPwcHK5GNag6RfLxnQV+iVZ9KNH1yQgSiQI+BBMBAgAo -AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCWglh+gUJBaNgWAAKCRDojTM0+l9qCgQ2 -D/4udJpV4zGIZW1yNaVvtd3vfKsTLi7GIRJLUBqVb2Yx/uhnN8jTl/tAhCVosCQ1pzvi9kMl -s8qO1vu2kw5EWFFkwK96roI8pTql3VIjwhRVQrCkR7oAk/eUd1U/nt2q6J4UTYeVgqbq4dsI -ZZTRyPJMD667YpuAIcaah+w9j/E5xksYQdMeprnDrQkkBCb4FIMqfDzBPKvEa8DcQr949K85 -kxhr6LDq9i5l4Egxt2JdH8DaR4GLca6+oHy0MyPs/bZOsfmZUObfM2oZgPpqYM96JanhzO1j -dpnItyBii2pc+kNx5nMOf4eikE/MBv+WUJ0TttWzApGGmFUzDhtuEvRH9NBjtJ/pMrYspIGu -O/QNY5KKOKQTvVIlwGcm8dTsSkqtBDSUwZyWbfKfKOI1/RhM9dC3gj5/BOY57DYYV4rdTK01 -ZtYjuhdfs2bhuP1uF/cgnSSZlv8azvf7Egh7tHPnYxvLjfq1bJAhCIX0hNg0a81/ndPAEFky -fSko+JPKvdSvsUcSi2QQ4U2HX//jNBjXRfG4F0utgbJnhXzEckz6gqt7wSDZH2oddVuO8Ssc -T7sK+CdXthSKnRyuI+sGUpG+6glpKWIfYkWFKNZWuQ+YUatY3QEDHXTIioycSmV8p4d/g/0S -V6TegidLxY8bXMkbqz+3n6FArRffv5MH7qt3cYkCPgQTAQIAKAUCWCXhOwIbAwUJAeEzgAYL -CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6I0zNPpfagrN/w/+Igp3vtYdNunikw3yHnYf -Jkm0MmaMDUM9mtsaXVN6xb9n25N3Xa3GWCpmdsbYZ8334tI/oQ4/NHq/bEI5WFH5F1aFkMkm -5AJVLuUkipCtmCZ5NkbRPJA9l0uNUUE6uuFXBhf4ddu7jb0jMetRF/kifJHVCCo5fISUNhLp -7bwcWq9qgDQNZNYMOo4s9WX5Tl+5x4gTZdd2/cAYt49h/wnkw+huM+Jm0GojpLqIQ1jZiffm -otf5rF4L+JhIIdW0W4IIh1v9BhHVllXw+z9oj0PALstT5h8/DuKoIiirFJ4DejU85GR1KKAS -DeO19G/lSpWj1rSgFv2N2gAOxq0X+BbQTua2jdcY6JpHR4H1JJ2wzfHsHPgDQcgY1rGlmjVF -aqU73WV4/hzXc/HshK/k4Zd8uD4zypv6rFsZ3UemK0aL2zXLVpV8SPWQ61nS03x675SmDlYr -A80ENfdqvsn00JQuBVIv4Tv0Ub7NfDraDGJCst8rObjBT/0vnBWTBCebb2EsnS2iStIFkWdz -/WXs4L4Yzre1iJwqRjiuqahZR5jHsjAUf2a0O29HVHE7zlFtCFmLPClml2lGQfQOpm5klGZF -rmvus+qZ9rt35UgWHPZezykkwtWrFOwspwuCWaPDto6tgbRJZ4ftitpdYYM3dKW9IGJXBwrt -BQrMsu+lp0vDF+yJAlUEEwEIAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEErpbt -lp5HmwCE8+F/6I0zNPpfagoFAmEAEJwFCQycmLgACgkQ6I0zNPpfagpWoBAAhOcbMAUw6Zt0 -GYzT3sR5/c0iatezPzXEXJf9ebzR8M5uPElXcxcnMx1dvXZmGPXPJKCPa99WCu1NZYy8F+Wj -GTOY9tfIkvSxhys1p/giPAmvid6uQmD+bz7ivktnyzCkDWfMA+l8lsCSEqVlaq6y5T+a6SWB -6TzC2S0MPb/RrC/7DpwyrNYWumvyVJh09adm1Mw/UGgst/sZ8eMaRYEd3X0yyT1CBpX4zp2E -qQj9IEOTizvzv1x2jkHe5ZUeU3+nTBNlhSA+WFHUi0pfBdo2qog3Mv2EC1P2qMKoSdD5tPbA -zql1yKoHHnXOMsqdftGwbiv2sYXWvrYvmaCd3Ys/viOyt3HOy9uV2ZEtBd9Yqo9x/NZj8QMA -nY5k8jjrIXbUC89MqrJsQ6xxWQIg5ikMT7DvY0Ln89ev4oJyVvwIQAwCm4jUzFNm9bZLYDOP -5lGJCV7tF5NYVU7NxNM8vescKc40mVNK/pygS5mxhK9QYOUjZsIv8gddrl1TkqrFMuxFnTyN -WvzE29wFu/n4N1DkF+ZBqS70SlRvB+Hjz5LrDgEzF1Wf1eA/wq1dZbvMjjDVIc2VGlYp8Cp2 -8ob23c1seTtYXTNYgSR5go4EpH+xi+bIWv01bQQ9xGwBbT5sm4WUeWOcmX4QewzLZ3T/wK9+ -N4Ye/hmU9O34FwWJOY58EIe0OUV0aGVyZXVtIEZvdW5kYXRpb24gU2VjdXJpdHkgVGVhbSA8 -c2VjdXJpdHlAZXRoZXJldW0ub3JnPokCHAQRAQgABgUCWhQmOgAKCRB6DAN0NP5372LSEACT -wZk1TASWZj5QF7rmkIM1GEyBxLE+PundNcMgM9Ktj1315ED8SmiukNI4knVS1MY99OIgXhQl -D1foF2GKdTomrwwC4012zTNyUYCY60LnPZ6Z511HG+rZgZtZrbkz0IiUpwAlhGQND77lBqem -J3K+CFX2XpDA/ojui/kqrY4cwMT5P8xPJkwgpRgw/jgdcZyJTsXdHblV9IGU4H1Vd1SgcfAf -Db3YxDUlBtzlp0NkZqxen8irLIXUQvsfuIfRUbUSkWoK/n3U/gOCajAe8ZNF07iX4OWjH4Sw -NDA841WhFWcGE+d8+pfMVfPASU3UPKH72uw86b2VgR46Av6voyMFd1pj+yCA+YAhJuOpV4yL -QaGg2Z0kVOjuNWK/kBzp1F58DWGh4YBatbhE/UyQOqAAtR7lNf0M3QF9AdrHTxX8oZeqVW3V -Fmi2mk0NwCIUv8SSrZr1dTchp04OtyXe5gZBXSfzncCSRQIUDC8OgNWaOzAaUmK299v4bvye -uSCxOysxC7Q1hZtjzFPKdljS81mRlYeUL4fHlJU9R57bg8mriSXLmn7eKrSEDm/EG5T8nRx7 -TgX2MqJs8sWFxD2+bboVEu75yuFmZ//nmCBApAit9Hr2/sCshGIEpa9MQ6xJCYUxyqeJH+Cc -Aja0UfXhnK2uvPClpJLIl4RE3gm4OXeE1IkCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYC -AwECHgECF4AFAloJYfoFCQWjYFgACgkQ6I0zNPpfagr4MQ//cfp3GSbSG8dkqgctW67Fy7cQ -diiTmx3cwxY+tlI3yrNmdjtrIQMzGdqtY6LNz7aN87F8mXNf+DyVHX9+wd1Y8U+E+hVCTzKC -sefUfxTz6unD9TTcGqaoelgIPMn4IiKz1RZE6eKpfDWe6q78W1Y6x1bE0qGNSjqT/QSxpezF -E/OAm/t8RRxVxDtqz8LfH2zLea5zaC+ADj8EqgY9vX9TQa4DyVV8MgOyECCCadJQCD5O5hIA -B2gVDWwrAUw+KBwskXZ7Iq4reJTKLEmt5z9zgtJ/fABwaCFt66ojwg0/RjbO9cNA3ZwHLGwU -C6hkb6bRzIoZoMfYxVS84opiqf/Teq+t/XkBYCxbSXTJDA5MKjcVuw3N6YKWbkGP/EfQThe7 -BfAKFwwIw5YmsWjHK8IQj6R6hBxzTz9rz8y1Lu8EAAFfA7OJKaboI2qbOlauH98OuOUmVtr1 -TczHO+pTcgWVN0ytq2/pX5KBf4vbmULNbg3HFRq+gHx8CW+jyXGkcqjbgU/5FwtDxeqRTdGJ -SyBGNBEU6pBNolyynyaKaaJjJ/biY27pvjymL5rlz95BH3Dn16Z4RRmqwlT6eq/wFYginujg -CCE1icqOSE+Vjl7V8tV8AcgANkXKdbBE+Q8wlKsGI/kS1w4XFAYcaNHFT8qNeS8TSFXFhvU8 -HylYxO79t56JAj4EEwECACgFAlgl3tgCGwMFCQHhM4AGCwkIBwMCBhUIAgkKCwQWAgMBAh4B -AheAAAoJEOiNMzT6X2oKmUMP/0hnaL6bVyepAq2LIdvIUbHfagt/Oo/KVfZs4bkM+xJOitJR -0kwZV9PTihXFdzhL/YNWc2+LtEBtKItqkJZKmWC0E6OPXGVuU6hfFPebuzVccYJfm0Q3Ej19 -VJI9Uomf59Bpak8HYyEED7WVQjoYn7XVPsonwus/9+LDX+c5vutbrUdbjga3KjHbewD93X4O -wVVoXyHEmU2Plyg8qvzFbNDylCWO7N2McO6SN6+7DitGZGr2+jO+P2R4RT1cnl2V3IRVcWZ0 -OTspPSnRGVr2fFiHN/+v8G/wHPLQcJZFvYPfUGNdcYbTmhWdiY0bEYXFiNrgzCCsyad7eKUR -WN9QmxqmyqLDjUEDJCAh19ES6Vg3tqGwXk+uNUCoF30ga0TxQt6UXZJDEQFAGeASQ/RqE/q1 -EAuLv8IGM8o7IqKO2pWfLuqsY6dTbKBwDzz9YOJt7EOGuPPQbHxaYStTushZmJnm7hi8lhVG -jT7qsEJdE95Il+I/mHWnXsCevaXjZugBiyV9yvOq4Hwwe2s1zKfrnQ4u0cadvGAh2eIqum7M -Y3o6nD47aJ3YmEPX/WnhI56bACa2GmWvUwjI4c0/er3esSPYnuHnM9L8Am4qQwMVSmyU80tC -MI7A9e13Mvv+RRkYFLJ7PVPdNpbW5jqX1doklFpKf6/XM+B+ngYneU+zgCUBiQJVBBMBCAA/ -AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBK6W7ZaeR5sAhPPhf+iNMzT6X2oKBQJh -ABCQBQkMnJi4AAoJEOiNMzT6X2oKAv0P+gJ3twBp5efNWyVLcIg4h4cOo9uD0NPvz8/fm2gX -FoOJL3MeigtPuSVfE9kuTaTuRbArzuFtdvH6G/kcRQvOlO4zyiIRHCk1gDHoIvvtn6RbRhVm -/Xo4uGIsFHst7n4A7BjicwEK5Op6Ih5Hoq19xz83YSBgBVk2fYEJIRyJiKFbyPjH0eSYe8v+ -Ra5/F85ugLx1P6mMVkW+WPzULns89riW7BGTnZmXFHZp8nO2pkUlcI7F3KRG7l4kmlC50ox6 -DiG/6AJCVulbAClky9C68TmJ/R1RazQxU/9IqVywsydq66tbJQbm5Z7GEti0C5jjbSRJL2oT -1xC7Rilr85PMREkPL3vegJdgj5PKlffZ/MocD/0EohiQ7wFpejFD4iTljeh0exRUwCRb6655 -9ib34JSQgU8Hl4JJu+mEgd9v0ZHD0/1mMD6fnAR84zca+O3cdASbnQmzTOKcGzLIrkE8TEnU -+2UZ8Ol7SAAqmBgzY1gKOilUho6dkyCAwNL+QDpvrITDPLEFPsjyB/M2KudZSVEn+Rletju1 -qkMW31qFMNlsbwzMZw+0USeGcs31Cs0B2/WQsro99CExlhS9auUFkmoVjJmYVTIYOM0zuPa4 -OyGspqPhRu5hEsmMDPDWD7Aad5k4GTqogQNnuKyRliZjXXrDZqFD5nfsJSL8Ky/sJGEMuQIN -BFgl3tgBEACbgq6HTN5gEBi0lkD/MafInmNi+59U5gRGYqk46WlfRjhHudXjDpgD0lolGb4h -YontkMaKRlCg2Rvgjvk3Zve0PKWjKw7gr8YBa9fMFY8BhAXI32OdyI9rFhxEZFfWAfwKVmT1 -9BdeAQRFvcfd+8w8f1XVc+zddULMJFBTr+xKDlIRWwTkdLPQeWbjo0eHl/g4tuLiLrTxVbnj -26bf+2+1DbM/w5VavzPrkviHqvKe/QP/gay4QDViWvFgLb90idfAHIdsPgflp0VDS5rVHFL6 -D73rSRdIRo3I8c8mYoNjSR4XDuvgOkAKW9LR3pvouFHHjp6Fr0GesRbrbb2EG66iPsR99MQ7 -FqIL9VMHPm2mtR+XvbnKkH2rYyEqaMbSdk29jGapkAWle4sIhSKk749A4tGkHl08KZ2N9o6G -rfUehP/V2eJLaph2DioFL1HxRryrKy80QQKLMJRekxigq8greW8xB4zuf9Mkuou+RHNmo8Pe -bHjFstLigiD6/zP2e+4tUmrT0/JTGOShoGMl8Rt0VRxdPImKun+4LOXbfOxArOSkY6i35+gs -gkkSy1gTJE0BY3S9auT6+YrglY/TWPQ9IJxWVOKlT+3WIp5wJu2bBKQ420VLqDYzkoWytel/ -bM1ACUtipMiIVeUs2uFiRjpzA1Wy0QHKPTdSuGlJPRrfcQARAQABiQIlBBgBAgAPAhsMBQJa -CWIIBQkFo2BYAAoJEOiNMzT6X2oKgSwQAKKs7BGF8TyZeIEO2EUK7R2bdQDCdSGZY06tqLFg -3IHMGxDMb/7FVoa2AEsFgv6xpoebxBB5zkhUk7lslgxvKiSLYjxfNjTBltfiFJ+eQnf+OTs8 -KeR51lLa66rvIH2qUzkNDCCTF45H4wIDpV05AXhBjKYkrDCrtey1rQyFp5fxI+0IQ1UKKXvz -ZK4GdxhxDbOUSd38MYy93nqcmclGSGK/gF8XiyuVjeifDCM6+T1NQTX0K9lneidcqtBDvlgg -JTLJtQPO33o5EHzXSiud+dKth1uUhZOFEaYRZoye1YE3yB0TNOOE8fXlvu8iuIAMBSDL9ep6 -sEIaXYwoD60I2gHdWD0lkP0DOjGQpi4ouXM3Edsd5MTi0MDRNTij431kn8T/D0LCgmoUmYYM -BgbwFhXr67axPZlKjrqR0z3F/Elv0ZPPcVg1tNznsALYQ9Ovl6b5M3cJ5GapbbvNWC7yEE1q -Scl9HiMxjt/H6aPastH63/7wcN0TslW+zRBy05VNJvpWGStQXcngsSUeJtI1Gd992YNjUJq4 -/Lih6Z1TlwcFVap+cTcDptoUvXYGg/9mRNNPZwErSfIJ0Ibnx9wPVuRN6NiCLOt2mtKp2F1p -M6AOQPpZ85vEh6I8i6OaO0w/Z0UHBwvpY6jDUliaROsWUQsqz78Z34CVj4cy6vPW2EF4iQIl -BBgBAgAPBQJYJd7YAhsMBQkB4TOAAAoJEOiNMzT6X2oKTjgP/1ojCVyGyvHMLUgnX0zwrR5Q -1M5RKFz6kHwKjODVLR3Isp8I935oTQt3DY7yFDI4t0GqbYRQMtxcNEb7maianhK2trCXfhPs -6/L04igjDf5iTcmzamXN6xnh5xkz06hZJJCMuu4MvKxC9MQHCVKAwjswl/9H9JqIBXAY3E2l -LpX5P+5jDZuPxS86p3+k4Rrdp9KTGXjiuEleM3zGlz5BLWydqovOck7C2aKh27ETFpDYY0z3 -yQ5AsPJyk1rAr0wrH6+ywmwWlzuQewavnrLnJ2M8iMFXpIhyHeEIU/f7o8f+dQk72rZ9CGzd -cqig2za/BS3zawZWgbv2vB2elNsIllYLdir45jxBOxx2yvJvEuu4glz78y4oJTCTAYAbMlle -5gVdPkVcGyvvVS9tinnSaiIzuvWrYHKWll1uYPm2Q1CDs06P5I7bUGAXpgQLUh/XQguy/0sX -GWqW3FS5JzP+XgcR/7UASvwBdHylubKbeqEpB7G1s+m+8C67qOrc7EQv3Jmy1YDOkhEyNig1 -rmjplLuir3tC1X+D7dHpn7NJe7nMwFx2b2MpMkLA9jPPAGPp/ekcu5sxCe+E0J/4UF++K+CR -XIxgtzU2UJfp8p9x+ygbx5qHinR0tVRdIzv3ZnGsXrfxnWfSOaB582cU3VRN9INzHHax8ETa -QVDnGO5uQa+FiQI8BBgBCAAmAhsMFiEErpbtlp5HmwCE8+F/6I0zNPpfagoFAmEAELYFCQyc -mN4ACgkQ6I0zNPpfagoqAQ/+MnDjBx8JWMd/XjeFoYKx/Oo0ntkInV+ME61JTBls4PdVk+TB -8PWZdPQHw9SnTvRmykFeznXIRzuxkowjrZYXdPXBxY2b1WyD5V3Ati1TM9vqpaR4osyPs2xy -I4dzDssh9YvUsIRL99O04/65lGiYeBNuACq+yK/7nD/ErzBkDYJHhMCdadbVWUACxvVIDvro -yQeVLKMsHqMCd8BTGD7VDs79NXskPnN77pAFnkzS4Z2b8SNzrlgTc5pUiuZHIXPIpEYmsYzh -ucTU6uI3dN1PbSFHK5tG2pHb4ZrPxY3L20Dgc2Tfu5/SDApZzwvvKTqjdO891MEJ++H+ssOz -i4O1UeWKs9owWttan9+PI47ozBSKOTxmMqLSQ0f56Np9FJsV0ilGxRKfjhzJ4KniOMUBA7mP -+m+TmXfVtthJred4sHlJMTJNpt+sCcT6wLMmyc3keIEAu33gsJj3LTpkEA2q+V+ZiP6Q8HRB -402ITklABSArrPSE/fQU9L8hZ5qmy0Z96z0iyILgVMLuRCCfQOMWhwl8yQWIIaf1yPI07xur -epy6lH7HmxjjOR7eo0DaSxQGQpThAtFGwkWkFh8yki8j3E42kkrxvEyyYZDXn2YcI3bpqhJx -PtwCMZUJ3kc/skOrs6bOI19iBNaEoNX5Dllm7UHjOgWNDQkcCuOCxucKano= -=arte +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 +6F7hEeTW+gnXEI2gPjfb5w== +=b5eA -----END PGP PUBLIC KEY BLOCK----- ``` diff --git a/cmd/devp2p/internal/ethtest/testdata/genesis.json b/cmd/devp2p/internal/ethtest/testdata/genesis.json index e8bb66bb3c1a..4cfebdcac10d 100644 --- a/cmd/devp2p/internal/ethtest/testdata/genesis.json +++ b/cmd/devp2p/internal/ethtest/testdata/genesis.json @@ -18,7 +18,6 @@ "shanghaiTime": 780, "cancunTime": 840, "terminalTotalDifficulty": 9454784, - "terminalTotalDifficultyPassed": true, "ethash": {} }, "nonce": "0x0", diff --git a/cmd/geth/genesis_test.go b/cmd/geth/genesis_test.go index ffe8176b0138..f5d21cc00b4d 100644 --- a/cmd/geth/genesis_test.go +++ b/cmd/geth/genesis_test.go @@ -29,7 +29,7 @@ var customGenesisTests = []struct { query string result string }{ - // Genesis file with an empty chain configuration (ensure missing fields work) + // Genesis file with a mostly-empty chain configuration (ensure missing fields work) { genesis: `{ "alloc" : {}, @@ -41,8 +41,8 @@ var customGenesisTests = []struct { "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp" : "0x00", - "config" : { - "terminalTotalDifficultyPassed": true + "config": { + "terminalTotalDifficulty": 0 } }`, query: "eth.getBlock(0).nonce", @@ -64,7 +64,7 @@ var customGenesisTests = []struct { "homesteadBlock" : 42, "daoForkBlock" : 141, "daoForkSupport" : true, - "terminalTotalDifficultyPassed" : true + "terminalTotalDifficulty": 0 } }`, query: "eth.getBlock(0).nonce", @@ -114,8 +114,8 @@ func TestCustomBackend(t *testing.T) { "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp" : "0x00", - "config" : { - "terminalTotalDifficultyPassed": true + "config": { + "terminalTotalDifficulty": 0 } }` type backendTest struct { diff --git a/cmd/geth/testdata/clique.json b/cmd/geth/testdata/clique.json index 36f5c3105703..d318f4c16612 100644 --- a/cmd/geth/testdata/clique.json +++ b/cmd/geth/testdata/clique.json @@ -8,7 +8,7 @@ "byzantiumBlock": 0, "constantinopleBlock": 0, "petersburgBlock": 0, - "terminalTotalDifficultyPassed": true, + "terminalTotalDifficulty": 0, "clique": { "period": 5, "epoch": 30000 @@ -22,4 +22,4 @@ "balance": "300000" } } -} \ No newline at end of file +} diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b47572a08154..2f00d40957e0 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1948,9 +1948,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if err != nil { Fatalf("Could not read genesis from database: %v", err) } - if !genesis.Config.TerminalTotalDifficultyPassed { - Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficultyPassed must be true") - } if genesis.Config.TerminalTotalDifficulty == nil { Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified") } else if genesis.Config.TerminalTotalDifficulty.Cmp(big.NewInt(0)) != 0 { diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index ae4c9f29a1cd..4ee19c7d4d6e 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -28,6 +28,7 @@ import ( "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/params" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" @@ -115,9 +116,6 @@ func errOut(n int, err error) chan error { func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) { // TTD is not defined yet, all headers should be in legacy format. ttd := chain.Config().TerminalTotalDifficulty - if ttd == nil { - return headers, nil, nil - } ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1) if ptd == nil { return nil, nil, consensus.ErrUnknownAncestor @@ -349,7 +347,7 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine and processes withdrawals on top. -func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { +func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) { if !beacon.IsPoSHeader(header) { beacon.ethone.Finalize(chain, header, state, body) return @@ -494,9 +492,6 @@ func (beacon *Beacon) SetThreads(threads int) { // It depends on the parentHash already being stored in the database. // If the parentHash is not stored in the database a UnknownAncestor error is returned. func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) { - if chain.Config().TerminalTotalDifficulty == nil { - return false, nil - } td := chain.GetTd(parentHash, parentNumber) if td == nil { return false, consensus.ErrUnknownAncestor diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index e58bb6203447..d31efd744510 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "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/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" @@ -573,7 +574,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine. There is no post-transaction // consensus rules in clique, do nothing here. -func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { +func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) { // No block rewards in PoA, so the state remains as is } diff --git a/consensus/consensus.go b/consensus/consensus.go index 9232f7a2c8bf..ff76d31f551f 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -23,6 +23,7 @@ import ( "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" "github.com/ethereum/go-ethereum/rpc" ) @@ -88,7 +89,7 @@ type Engine interface { // // Note: The state database might be updated to reflect any consensus rules // that happen at finalization (e.g. block rewards). - Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) + Finalize(chain ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block // rewards or process withdrawals) and assembles the final block. diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 3d3c9cf91833..4f92f1282b9e 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -30,6 +30,7 @@ import ( "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/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -503,7 +504,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine, accumulating the block and uncle rewards. -func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { +func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) { // Accumulate any block and uncle rewards accumulateRewards(chain.Config(), state, header, body.Uncles) } @@ -566,7 +567,7 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) { // accumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // included uncles. The coinbase of each uncle block is also rewarded. -func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, header *types.Header, uncles []*types.Header) { +func accumulateRewards(config *params.ChainConfig, stateDB vm.StateDB, header *types.Header, uncles []*types.Header) { // Select the correct block reward based on chain progression blockReward := FrontierBlockReward if config.IsByzantium(header.Number) { diff --git a/consensus/misc/dao.go b/consensus/misc/dao.go index 45669d0bcec8..b80c1b833a47 100644 --- a/consensus/misc/dao.go +++ b/consensus/misc/dao.go @@ -21,11 +21,10 @@ import ( "errors" "math/big" - "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/params" - "github.com/holiman/uint256" ) var ( @@ -74,7 +73,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header) // ApplyDAOHardFork modifies the state database according to the DAO hard-fork // rules, transferring all balances of a set of DAO accounts to a single refund // contract. -func ApplyDAOHardFork(statedb *state.StateDB) { +func ApplyDAOHardFork(statedb vm.StateDB) { // Retrieve the contract to refund balances into if !statedb.Exist(params.DAORefundContract) { statedb.CreateAccount(params.DAORefundContract) @@ -82,7 +81,8 @@ func ApplyDAOHardFork(statedb *state.StateDB) { // Move every DAO account and extra-balance account funds into the refund contract for _, addr := range params.DAODrainList() { - statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract) - statedb.SetBalance(addr, new(uint256.Int), tracing.BalanceDecreaseDaoAccount) + balance := statedb.GetBalance(addr) + statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract) + statedb.SubBalance(addr, balance, tracing.BalanceDecreaseDaoAccount) } } diff --git a/core/block_validator_test.go b/core/block_validator_test.go index 80e682066163..8af4057693e9 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -113,8 +113,12 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) { } copy(gspec.ExtraData[32:], addr[:]) + // chain_maker has no blockchain to retrieve the TTD from, setting to nil + // is a hack to signal it to generate pre-merge blocks + gspec.Config.TerminalTotalDifficulty = nil td := 0 genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil) + for i, block := range blocks { header := block.Header() if i > 0 { @@ -145,7 +149,6 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) { } preBlocks = blocks gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td)) - t.Logf("Set ttd to %v\n", gspec.Config.TerminalTotalDifficulty) postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) { gen.SetPoS() }) diff --git a/core/blockchain.go b/core/blockchain.go index 1d45a298e4b0..c3da61b28108 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1774,7 +1774,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness if err != nil { return nil, it.index, err } - statedb.SetLogger(bc.logger) // If we are past Byzantium, enable prefetching to pull in trie node paths // while processing transactions. Before Byzantium the prefetcher is mostly diff --git a/core/blockchain_test.go b/core/blockchain_test.go index b8c4678ac801..05629cd19f89 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -4092,7 +4092,6 @@ func TestEIP3651(t *testing.T) { gspec.Config.BerlinBlock = common.Big0 gspec.Config.LondonBlock = common.Big0 gspec.Config.TerminalTotalDifficulty = common.Big0 - gspec.Config.TerminalTotalDifficultyPassed = true gspec.Config.ShanghaiTime = u64(0) signer := types.LatestSigner(gspec.Config) diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index 61d09117bddc..f72e6285dfa3 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -57,7 +57,6 @@ func TestGeneratePOSChain(t *testing.T) { db = rawdb.NewMemoryDatabase() ) - config.TerminalTotalDifficultyPassed = true config.TerminalTotalDifficulty = common.Big0 config.ShanghaiTime = u64(0) config.CancunTime = u64(0) diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index ec6c27b48dbe..de589c0d44f6 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -378,26 +378,25 @@ func TestTimeBasedForkInGenesis(t *testing.T) { forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes())) config = func(shanghai, cancun uint64) *params.ChainConfig { return ¶ms.ChainConfig{ - ChainID: big.NewInt(1337), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - MergeNetsplitBlock: big.NewInt(0), - ShanghaiTime: &shanghai, - CancunTime: &cancun, - Ethash: new(params.EthashConfig), + ChainID: big.NewInt(1337), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(0), + MergeNetsplitBlock: big.NewInt(0), + ShanghaiTime: &shanghai, + CancunTime: &cancun, + Ethash: new(params.EthashConfig), } } ) diff --git a/core/genesis_test.go b/core/genesis_test.go index 0fee8741386a..9eacf2024c68 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -257,31 +257,30 @@ func newDbConfig(scheme string) *triedb.Config { func TestVerkleGenesisCommit(t *testing.T) { var verkleTime uint64 = 0 verkleConfig := ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: false, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - MergeNetsplitBlock: nil, - ShanghaiTime: &verkleTime, - CancunTime: &verkleTime, - PragueTime: &verkleTime, - VerkleTime: &verkleTime, - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - Ethash: nil, - Clique: nil, + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: nil, + ShanghaiTime: &verkleTime, + CancunTime: &verkleTime, + PragueTime: &verkleTime, + VerkleTime: &verkleTime, + TerminalTotalDifficulty: big.NewInt(0), + Ethash: nil, + Clique: nil, } genesis := &Genesis{ diff --git a/core/state/state_object.go b/core/state/state_object.go index 1ab432e96e9b..b659bf7ff208 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -23,7 +23,6 @@ import ( "time" "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/log" @@ -208,19 +207,18 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { } // SetState updates a value in account storage. -func (s *stateObject) SetState(key, value common.Hash) { +// It returns the previous value +func (s *stateObject) SetState(key, value common.Hash) common.Hash { // If the new value is the same as old, don't set. Otherwise, track only the // dirty changes, supporting reverting all of it back to no change. prev, origin := s.getState(key) if prev == value { - return + return prev } // New value is different, update and journal the change s.db.journal.storageChange(s.address, key, prev, origin) s.setState(key, value, origin) - if s.db.logger != nil && s.db.logger.OnStorageChange != nil { - s.db.logger.OnStorageChange(s.address, key, prev, value) - } + return prev } // setState updates a value in account dirty storage. The dirtiness will be @@ -448,33 +446,25 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) { // AddBalance adds amount to s's balance. // It is used to add funds to the destination account of a transfer. -func (s *stateObject) AddBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { +// returns the previous balance +func (s *stateObject) AddBalance(amount *uint256.Int) uint256.Int { // EIP161: We must check emptiness for the objects such that the account // clearing (0,0,0 objects) can take effect. if amount.IsZero() { if s.empty() { s.touch() } - return + return *(s.Balance()) } - s.SetBalance(new(uint256.Int).Add(s.Balance(), amount), reason) + return s.SetBalance(new(uint256.Int).Add(s.Balance(), amount)) } -// SubBalance removes amount from s's balance. -// It is used to remove funds from the origin account of a transfer. -func (s *stateObject) SubBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { - if amount.IsZero() { - return - } - s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount), reason) -} - -func (s *stateObject) SetBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { +// SetBalance sets the balance for the object, and returns the previous balance. +func (s *stateObject) SetBalance(amount *uint256.Int) uint256.Int { + prev := *s.data.Balance s.db.journal.balanceChange(s.address, s.data.Balance) - if s.db.logger != nil && s.db.logger.OnBalanceChange != nil { - s.db.logger.OnBalanceChange(s.address, s.Balance().ToBig(), amount.ToBig(), reason) - } s.setBalance(amount) + return prev } func (s *stateObject) setBalance(amount *uint256.Int) { @@ -547,10 +537,6 @@ func (s *stateObject) CodeSize() int { func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { s.db.journal.setCode(s.address) - if s.db.logger != nil && s.db.logger.OnCodeChange != nil { - // TODO remove prevcode from this callback - s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), nil, codeHash, code) - } s.setCode(codeHash, code) } @@ -562,9 +548,6 @@ func (s *stateObject) setCode(codeHash common.Hash, code []byte) { func (s *stateObject) SetNonce(nonce uint64) { s.db.journal.nonceChange(s.address, s.data.Nonce) - if s.db.logger != nil && s.db.logger.OnNonceChange != nil { - s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce) - } s.setNonce(nonce) } diff --git a/core/state/state_test.go b/core/state/state_test.go index 9de50beb12dc..6f54300c37ad 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -23,7 +23,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" - "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/triedb" @@ -48,11 +47,11 @@ func TestDump(t *testing.T) { // generate a few entries obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01})) - obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified) + obj1.AddBalance(uint256.NewInt(22)) obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02})) - obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified) + obj3.SetBalance(uint256.NewInt(44)) // write some of them to the trie s.state.updateStateObject(obj1) @@ -106,13 +105,13 @@ func TestIterativeDump(t *testing.T) { // generate a few entries obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01})) - obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified) + obj1.AddBalance(uint256.NewInt(22)) obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02})) - obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified) + obj3.SetBalance(uint256.NewInt(44)) obj4 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x00})) - obj4.AddBalance(uint256.NewInt(1337), tracing.BalanceChangeUnspecified) + obj4.AddBalance(uint256.NewInt(1337)) // write some of them to the trie s.state.updateStateObject(obj1) @@ -200,7 +199,7 @@ func TestCreateObjectRevert(t *testing.T) { state.CreateAccount(addr) so0 := state.getStateObject(addr) - so0.SetBalance(uint256.NewInt(42), tracing.BalanceChangeUnspecified) + so0.SetBalance(uint256.NewInt(42)) so0.SetNonce(43) so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) state.setStateObject(so0) diff --git a/core/state/statedb.go b/core/state/statedb.go index f7efc199b3dc..0183c14480df 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -21,7 +21,6 @@ import ( "errors" "fmt" "maps" - "math/big" "slices" "sync" "sync/atomic" @@ -81,7 +80,6 @@ type StateDB struct { db Database prefetcher *triePrefetcher trie Trie - logger *tracing.Hooks reader Reader // originalRoot is the pre-state root, before any changes were made. @@ -189,11 +187,6 @@ func New(root common.Hash, db Database) (*StateDB, error) { return sdb, nil } -// SetLogger sets the logger for account update hooks. -func (s *StateDB) SetLogger(l *tracing.Hooks) { - s.logger = l -} - // StartPrefetcher initializes a new trie prefetcher to pull in nodes from the // state trie concurrently while the state is mutated so that when we reach the // commit phase, most of the needed data is already hot. @@ -247,9 +240,6 @@ func (s *StateDB) AddLog(log *types.Log) { log.TxHash = s.thash log.TxIndex = uint(s.txIndex) log.Index = s.logSize - if s.logger != nil && s.logger.OnLog != nil { - s.logger.OnLog(log) - } s.logs[s.thash] = append(s.logs[s.thash], log) s.logSize++ } @@ -409,25 +399,30 @@ func (s *StateDB) HasSelfDestructed(addr common.Address) bool { */ // AddBalance adds amount to the account associated with addr. -func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { +func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int { stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.AddBalance(amount, reason) + if stateObject == nil { + return uint256.Int{} } + return stateObject.AddBalance(amount) } // SubBalance subtracts amount from the account associated with addr. -func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { +func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int { stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.SubBalance(amount, reason) + if stateObject == nil { + return uint256.Int{} + } + if amount.IsZero() { + return *(stateObject.Balance()) } + return stateObject.SetBalance(new(uint256.Int).Sub(stateObject.Balance(), amount)) } func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { stateObject := s.getOrNewStateObject(addr) if stateObject != nil { - stateObject.SetBalance(amount, reason) + stateObject.SetBalance(amount) } } @@ -445,11 +440,11 @@ func (s *StateDB) SetCode(addr common.Address, code []byte) { } } -func (s *StateDB) SetState(addr common.Address, key, value common.Hash) { - stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetState(key, value) +func (s *StateDB) SetState(addr common.Address, key, value common.Hash) common.Hash { + if stateObject := s.getOrNewStateObject(addr); stateObject != nil { + return stateObject.SetState(key, value) } + return common.Hash{} } // SetStorage replaces the entire storage for the specified account with given @@ -477,7 +472,7 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common if obj != nil { newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code) newObj.SetNonce(obj.Nonce()) - newObj.SetBalance(obj.Balance(), tracing.BalanceChangeUnspecified) + newObj.SetBalance(obj.Balance()) } } @@ -486,15 +481,17 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common // // The account's state object is still available until the state is committed, // getStateObject will return a non-nil account after SelfDestruct. -func (s *StateDB) SelfDestruct(addr common.Address) { +func (s *StateDB) SelfDestruct(addr common.Address) uint256.Int { stateObject := s.getStateObject(addr) + var prevBalance uint256.Int if stateObject == nil { - return + return prevBalance } + prevBalance = *(stateObject.Balance()) // Regardless of whether it is already destructed or not, we do have to // journal the balance-change, if we set it to zero here. if !stateObject.Balance().IsZero() { - stateObject.SetBalance(new(uint256.Int), tracing.BalanceDecreaseSelfdestruct) + stateObject.SetBalance(new(uint256.Int)) } // If it is already marked as self-destructed, we do not need to add it // for journalling a second time. @@ -502,16 +499,18 @@ func (s *StateDB) SelfDestruct(addr common.Address) { s.journal.destruct(addr) stateObject.markSelfdestructed() } + return prevBalance } -func (s *StateDB) Selfdestruct6780(addr common.Address) { +func (s *StateDB) SelfDestruct6780(addr common.Address) (uint256.Int, bool) { stateObject := s.getStateObject(addr) if stateObject == nil { - return + return uint256.Int{}, false } if stateObject.newContract { - s.SelfDestruct(addr) + return s.SelfDestruct(addr), true } + return *(stateObject.Balance()), false } // SetTransientState sets transient storage for a given account. It @@ -735,11 +734,6 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) { delete(s.stateObjects, obj.address) s.markDelete(addr) - - // If ether was sent to account post-selfdestruct it is burnt. - if bal := obj.Balance(); s.logger != nil && s.logger.OnBalanceChange != nil && obj.selfDestructed && bal.Sign() != 0 { - s.logger.OnBalanceChange(obj.address, bal.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestructBurn) - } // We need to maintain account deletions explicitly (will remain // set indefinitely). Note only the first occurred self-destruct // event is tracked. diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go new file mode 100644 index 000000000000..55b53ded40ff --- /dev/null +++ b/core/state/statedb_hooked.go @@ -0,0 +1,242 @@ +// 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 state + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/stateless" + "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/ethereum/go-ethereum/trie/utils" + "github.com/holiman/uint256" +) + +// hookedStateDB represents a statedb which emits calls to tracing-hooks +// on state operations. +type hookedStateDB struct { + inner *StateDB + hooks *tracing.Hooks +} + +// NewHookedState wraps the given stateDb with the given hooks +func NewHookedState(stateDb *StateDB, hooks *tracing.Hooks) *hookedStateDB { + s := &hookedStateDB{stateDb, hooks} + if s.hooks == nil { + s.hooks = new(tracing.Hooks) + } + return s +} + +func (s *hookedStateDB) CreateAccount(addr common.Address) { + s.inner.CreateAccount(addr) +} + +func (s *hookedStateDB) CreateContract(addr common.Address) { + s.inner.CreateContract(addr) +} + +func (s *hookedStateDB) GetBalance(addr common.Address) *uint256.Int { + return s.inner.GetBalance(addr) +} + +func (s *hookedStateDB) GetNonce(addr common.Address) uint64 { + return s.inner.GetNonce(addr) +} + +func (s *hookedStateDB) GetCodeHash(addr common.Address) common.Hash { + return s.inner.GetCodeHash(addr) +} + +func (s *hookedStateDB) GetCode(addr common.Address) []byte { + return s.inner.GetCode(addr) +} + +func (s *hookedStateDB) GetCodeSize(addr common.Address) int { + return s.inner.GetCodeSize(addr) +} + +func (s *hookedStateDB) AddRefund(u uint64) { + s.inner.AddRefund(u) +} + +func (s *hookedStateDB) SubRefund(u uint64) { + s.inner.SubRefund(u) +} + +func (s *hookedStateDB) GetRefund() uint64 { + return s.inner.GetRefund() +} + +func (s *hookedStateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { + return s.inner.GetCommittedState(addr, hash) +} + +func (s *hookedStateDB) GetState(addr common.Address, hash common.Hash) common.Hash { + return s.inner.GetState(addr, hash) +} + +func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash { + return s.inner.GetStorageRoot(addr) +} + +func (s *hookedStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash { + return s.inner.GetTransientState(addr, key) +} + +func (s *hookedStateDB) SetTransientState(addr common.Address, key, value common.Hash) { + s.inner.SetTransientState(addr, key, value) +} + +func (s *hookedStateDB) HasSelfDestructed(addr common.Address) bool { + return s.inner.HasSelfDestructed(addr) +} + +func (s *hookedStateDB) Exist(addr common.Address) bool { + return s.inner.Exist(addr) +} + +func (s *hookedStateDB) Empty(addr common.Address) bool { + return s.inner.Empty(addr) +} + +func (s *hookedStateDB) AddressInAccessList(addr common.Address) bool { + return s.inner.AddressInAccessList(addr) +} + +func (s *hookedStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) { + return s.inner.SlotInAccessList(addr, slot) +} + +func (s *hookedStateDB) AddAddressToAccessList(addr common.Address) { + s.inner.AddAddressToAccessList(addr) +} + +func (s *hookedStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { + s.inner.AddSlotToAccessList(addr, slot) +} + +func (s *hookedStateDB) PointCache() *utils.PointCache { + return s.inner.PointCache() +} + +func (s *hookedStateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) { + s.inner.Prepare(rules, sender, coinbase, dest, precompiles, txAccesses) +} + +func (s *hookedStateDB) RevertToSnapshot(i int) { + s.inner.RevertToSnapshot(i) +} + +func (s *hookedStateDB) Snapshot() int { + return s.inner.Snapshot() +} + +func (s *hookedStateDB) AddPreimage(hash common.Hash, bytes []byte) { + s.inner.Snapshot() +} + +func (s *hookedStateDB) Witness() *stateless.Witness { + return s.inner.Witness() +} + +func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int { + prev := s.inner.SubBalance(addr, amount, reason) + if s.hooks.OnBalanceChange != nil && !amount.IsZero() { + newBalance := new(uint256.Int).Sub(&prev, amount) + s.hooks.OnBalanceChange(addr, prev.ToBig(), newBalance.ToBig(), reason) + } + return prev +} + +func (s *hookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int { + prev := s.inner.AddBalance(addr, amount, reason) + if s.hooks.OnBalanceChange != nil && !amount.IsZero() { + newBalance := new(uint256.Int).Add(&prev, amount) + s.hooks.OnBalanceChange(addr, prev.ToBig(), newBalance.ToBig(), reason) + } + return prev +} + +func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64) { + s.inner.SetNonce(address, nonce) + if s.hooks.OnNonceChange != nil { + s.hooks.OnNonceChange(address, nonce-1, nonce) + } +} + +func (s *hookedStateDB) SetCode(address common.Address, code []byte) { + s.inner.SetCode(address, code) + if s.hooks.OnCodeChange != nil { + s.hooks.OnCodeChange(address, types.EmptyCodeHash, nil, crypto.Keccak256Hash(code), code) + } +} + +func (s *hookedStateDB) SetState(address common.Address, key common.Hash, value common.Hash) common.Hash { + prev := s.inner.SetState(address, key, value) + if s.hooks.OnStorageChange != nil && prev != value { + s.hooks.OnStorageChange(address, key, prev, value) + } + return prev +} + +func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int { + prev := s.inner.SelfDestruct(address) + if !prev.IsZero() { + if s.hooks.OnBalanceChange != nil { + s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) + } + } + return prev +} + +func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, bool) { + prev, changed := s.inner.SelfDestruct6780(address) + if !prev.IsZero() && changed { + if s.hooks.OnBalanceChange != nil { + s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) + } + } + return prev, changed +} + +func (s *hookedStateDB) AddLog(log *types.Log) { + // The inner will modify the log (add fields), so invoke that first + s.inner.AddLog(log) + if s.hooks.OnLog != nil { + s.hooks.OnLog(log) + } +} + +func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) { + defer s.inner.Finalise(deleteEmptyObjects) + if s.hooks.OnBalanceChange == nil { + return + } + for addr := range s.inner.journal.dirties { + obj := s.inner.stateObjects[addr] + if obj != nil && obj.selfDestructed { + // If ether was sent to account post-selfdestruct it is burnt. + if bal := obj.Balance(); bal.Sign() != 0 { + s.hooks.OnBalanceChange(addr, bal.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestructBurn) + } + } + } +} diff --git a/core/state/statedb_hooked_test.go b/core/state/statedb_hooked_test.go new file mode 100644 index 000000000000..9abd76b02db8 --- /dev/null +++ b/core/state/statedb_hooked_test.go @@ -0,0 +1,130 @@ +// 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 state + +import ( + "fmt" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" +) + +// This method tests that the 'burn' from sending-to-selfdestructed accounts +// is accounted for. +// (There is also a higher-level test in eth/tracers: TestSupplySelfDestruct ) +func TestBurn(t *testing.T) { + // Note: burn can happen even after EIP-6780, if within one single transaction, + // the following occur: + // 1. contract B creates contract A + // 2. contract A is destructed + // 3. constract B sends ether to A + + var burned = new(uint256.Int) + s, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + hooked := NewHookedState(s, &tracing.Hooks{ + OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) { + if reason == tracing.BalanceDecreaseSelfdestructBurn { + burned.Add(burned, uint256.MustFromBig(prev)) + } + }, + }) + createAndDestroy := func(addr common.Address) { + hooked.AddBalance(addr, uint256.NewInt(100), tracing.BalanceChangeUnspecified) + hooked.CreateContract(addr) + hooked.SelfDestruct(addr) + // sanity-check that balance is now 0 + if have, want := hooked.GetBalance(addr), new(uint256.Int); !have.Eq(want) { + t.Fatalf("post-destruct balance wrong: have %v want %v", have, want) + } + } + addA := common.Address{0xaa} + addB := common.Address{0xbb} + addC := common.Address{0xcc} + + // Tx 1: create and destroy address A and B in one tx + createAndDestroy(addA) + createAndDestroy(addB) + hooked.AddBalance(addA, uint256.NewInt(200), tracing.BalanceChangeUnspecified) + hooked.AddBalance(addB, uint256.NewInt(200), tracing.BalanceChangeUnspecified) + hooked.Finalise(true) + + // Tx 2: create and destroy address C, then commit + createAndDestroy(addC) + hooked.AddBalance(addC, uint256.NewInt(200), tracing.BalanceChangeUnspecified) + hooked.Finalise(true) + + s.Commit(0, false) + if have, want := burned, uint256.NewInt(600); !have.Eq(want) { + t.Fatalf("burn-count wrong, have %v want %v", have, want) + } +} + +// TestHooks is a basic sanity-check of all hooks +func TestHooks(t *testing.T) { + inner, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + inner.SetTxContext(common.Hash{0x11}, 100) // For the log + var result []string + var wants = []string{ + "0xaa00000000000000000000000000000000000000.balance: 0->100 (BalanceChangeUnspecified)", + "0xaa00000000000000000000000000000000000000.balance: 100->50 (BalanceChangeTransfer)", + "0xaa00000000000000000000000000000000000000.nonce: 1336->1337", + "0xaa00000000000000000000000000000000000000.code: (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470) ->0x1325 (0xa12ae05590de0c93a00bc7ac773c2fdb621e44f814985e72194f921c0050f728)", + "0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000000 ->0x0000000000000000000000000000000000000000000000000000000000000011", + "0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000011 ->0x0000000000000000000000000000000000000000000000000000000000000022", + "log 100", + } + emitF := func(format string, a ...any) { + result = append(result, fmt.Sprintf(format, a...)) + } + sdb := NewHookedState(inner, &tracing.Hooks{ + OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) { + emitF("%v.balance: %v->%v (%v)", addr, prev, new, reason) + }, + OnNonceChange: func(addr common.Address, prev, new uint64) { + emitF("%v.nonce: %v->%v", addr, prev, new) + }, + OnCodeChange: func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) { + emitF("%v.code: %#x (%v) ->%#x (%v)", addr, prevCode, prevCodeHash, code, codeHash) + }, + OnStorageChange: func(addr common.Address, slot common.Hash, prev, new common.Hash) { + emitF("%v.storage slot %v: %v ->%v", addr, slot, prev, new) + }, + OnLog: func(log *types.Log) { + emitF("log %v", log.TxIndex) + }, + }) + sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified) + sdb.SubBalance(common.Address{0xaa}, uint256.NewInt(50), tracing.BalanceChangeTransfer) + sdb.SetNonce(common.Address{0xaa}, 1337) + sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37}) + sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x11")) + sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22")) + sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x01")) + sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x02")) + sdb.AddLog(&types.Log{ + Address: common.Address{0xbb}, + }) + for i, want := range wants { + if have := result[i]; have != want { + t.Fatalf("error event %d, have\n%v\nwant%v\n", i, have, want) + } + } +} diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 3c19ec0591f5..3647397df6f8 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -170,7 +170,7 @@ func TestCopy(t *testing.T) { for i := byte(0); i < 255; i++ { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) - obj.AddBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) + obj.AddBalance(uint256.NewInt(uint64(i))) orig.updateStateObject(obj) } orig.Finalise(false) @@ -187,9 +187,9 @@ func TestCopy(t *testing.T) { copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i})) ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i})) - origObj.AddBalance(uint256.NewInt(2*uint64(i)), tracing.BalanceChangeUnspecified) - copyObj.AddBalance(uint256.NewInt(3*uint64(i)), tracing.BalanceChangeUnspecified) - ccopyObj.AddBalance(uint256.NewInt(4*uint64(i)), tracing.BalanceChangeUnspecified) + origObj.AddBalance(uint256.NewInt(2 * uint64(i))) + copyObj.AddBalance(uint256.NewInt(3 * uint64(i))) + ccopyObj.AddBalance(uint256.NewInt(4 * uint64(i))) orig.updateStateObject(origObj) copy.updateStateObject(copyObj) @@ -236,7 +236,7 @@ func TestCopyWithDirtyJournal(t *testing.T) { // Fill up the initial states for i := byte(0); i < 255; i++ { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) - obj.AddBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) + obj.AddBalance(uint256.NewInt(uint64(i))) obj.data.Root = common.HexToHash("0xdeadbeef") orig.updateStateObject(obj) } @@ -246,7 +246,9 @@ func TestCopyWithDirtyJournal(t *testing.T) { // modify all in memory without finalizing for i := byte(0); i < 255; i++ { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) - obj.SubBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) + amount := uint256.NewInt(uint64(i)) + obj.SetBalance(new(uint256.Int).Sub(obj.Balance(), amount)) + orig.updateStateObject(obj) } cpy := orig.Copy() @@ -280,7 +282,7 @@ func TestCopyObjectState(t *testing.T) { // Fill up the initial states for i := byte(0); i < 5; i++ { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) - obj.AddBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) + obj.AddBalance(uint256.NewInt(uint64(i))) obj.data.Root = common.HexToHash("0xdeadbeef") orig.updateStateObject(obj) } diff --git a/core/state/sync_test.go b/core/state/sync_test.go index 2416cda873db..b2c75e72fe33 100644 --- a/core/state/sync_test.go +++ b/core/state/sync_test.go @@ -22,7 +22,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" - "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/ethdb" @@ -62,7 +61,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, c obj := state.getOrNewStateObject(common.BytesToAddress([]byte{i})) acc := &testAccount{address: common.BytesToAddress([]byte{i})} - obj.AddBalance(uint256.NewInt(uint64(11*i)), tracing.BalanceChangeUnspecified) + obj.AddBalance(uint256.NewInt(uint64(11 * i))) acc.balance = uint256.NewInt(uint64(11 * i)) obj.SetNonce(uint64(42 * i)) diff --git a/core/state_processor.go b/core/state_processor.go index fe0304e81d67..ec499f892875 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -75,6 +75,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Apply pre-execution system calls. context = NewEVMBlockContext(header, p.chain, nil) + vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg) if beaconRoot := block.BeaconRoot(); beaconRoot != nil { ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) @@ -98,7 +99,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg receipts = append(receipts, receipt) allLogs = append(allLogs, receipt.Logs...) } - + var tracingStateDB = vm.StateDB(statedb) + if hooks := cfg.Tracer; hooks != nil { + tracingStateDB = state.NewHookedState(statedb, hooks) + } // Read requests if Prague is enabled. var requests [][]byte if p.config.IsPrague(block.Number(), block.Time()) { @@ -109,15 +113,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } requests = append(requests, depositRequests) // EIP-7002 withdrawals - withdrawalRequests := ProcessWithdrawalQueue(vmenv, statedb) + withdrawalRequests := ProcessWithdrawalQueue(vmenv, tracingStateDB) requests = append(requests, withdrawalRequests) // EIP-7251 consolidations - consolidationRequests := ProcessConsolidationQueue(vmenv, statedb) + consolidationRequests := ProcessConsolidationQueue(vmenv, tracingStateDB) requests = append(requests, consolidationRequests) } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.chain.engine.Finalize(p.chain, header, statedb, block.Body()) + p.chain.engine.Finalize(p.chain, header, tracingStateDB, block.Body()) return &ProcessResult{ Receipts: receipts, @@ -131,17 +135,20 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // and uses the input parameters for its environment similar to ApplyTransaction. However, // this method takes an already created EVM instance as input. func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) { - if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxStart != nil { - evm.Config.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) - if evm.Config.Tracer.OnTxEnd != nil { - defer func() { - evm.Config.Tracer.OnTxEnd(receipt, err) - }() + var tracingStateDB = vm.StateDB(statedb) + if hooks := evm.Config.Tracer; hooks != nil { + tracingStateDB = state.NewHookedState(statedb, hooks) + if hooks.OnTxStart != nil { + hooks.OnTxStart(evm.GetVMContext(), tx, msg.From) + } + if hooks.OnTxEnd != nil { + defer func() { hooks.OnTxEnd(receipt, err) }() } } + // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) - evm.Reset(txContext, statedb) + evm.Reset(txContext, tracingStateDB) // Apply the transaction to the current state (included in the env). result, err := ApplyMessage(evm, msg, gp) @@ -152,7 +159,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo // Update the state with pending changes. var root []byte if config.IsByzantium(blockNumber) { - statedb.Finalise(true) + tracingStateDB.Finalise(true) } else { root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes() } @@ -217,7 +224,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root // contract. This method is exported to be used in tests. -func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { +func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb vm.StateDB) { if tracer := vmenv.Config.Tracer; tracer != nil { if tracer.OnSystemCallStart != nil { tracer.OnSystemCallStart() @@ -243,7 +250,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *stat // ProcessParentBlockHash stores the parent block hash in the history storage contract // as per EIP-2935. -func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { +func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb vm.StateDB) { if tracer := vmenv.Config.Tracer; tracer != nil { if tracer.OnSystemCallStart != nil { tracer.OnSystemCallStart() @@ -269,17 +276,17 @@ func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb *state. // ProcessWithdrawalQueue calls the EIP-7002 withdrawal queue contract. // It returns the opaque request data returned by the contract. -func ProcessWithdrawalQueue(vmenv *vm.EVM, statedb *state.StateDB) []byte { +func ProcessWithdrawalQueue(vmenv *vm.EVM, statedb vm.StateDB) []byte { return processRequestsSystemCall(vmenv, statedb, 0x01, params.WithdrawalQueueAddress) } // ProcessConsolidationQueue calls the EIP-7251 consolidation queue contract. // It returns the opaque request data returned by the contract. -func ProcessConsolidationQueue(vmenv *vm.EVM, statedb *state.StateDB) []byte { +func ProcessConsolidationQueue(vmenv *vm.EVM, statedb vm.StateDB) []byte { return processRequestsSystemCall(vmenv, statedb, 0x02, params.ConsolidationQueueAddress) } -func processRequestsSystemCall(vmenv *vm.EVM, statedb *state.StateDB, requestType byte, addr common.Address) []byte { +func processRequestsSystemCall(vmenv *vm.EVM, statedb vm.StateDB, requestType byte, addr common.Address) []byte { if tracer := vmenv.Config.Tracer; tracer != nil { if tracer.OnSystemCallStart != nil { tracer.OnSystemCallStart() diff --git a/core/state_processor_test.go b/core/state_processor_test.go index b701ee651b50..2a16ef2cfb8f 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -51,23 +51,22 @@ func u64(val uint64) *uint64 { return &val } func TestStateProcessorErrors(t *testing.T) { var ( config = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - Ethash: new(params.EthashConfig), - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - ShanghaiTime: new(uint64), - CancunTime: new(uint64), + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + Ethash: new(params.EthashConfig), + TerminalTotalDifficulty: big.NewInt(0), + ShanghaiTime: new(uint64), + CancunTime: new(uint64), } signer = types.LatestSigner(config) key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -257,7 +256,7 @@ func TestStateProcessorErrors(t *testing.T) { want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1, baseFee: 875000000", }, } { - block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) + block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config, false) _, err := blockchain.InsertChain(types.Blocks{block}) if err == nil { t.Fatal("block imported without errors") @@ -306,7 +305,7 @@ func TestStateProcessorErrors(t *testing.T) { want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: transaction type not supported", }, } { - block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config) + block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config, true) _, err := blockchain.InsertChain(types.Blocks{block}) if err == nil { t.Fatal("block imported without errors") @@ -345,7 +344,7 @@ func TestStateProcessorErrors(t *testing.T) { want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1", }, } { - block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) + block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config, false) _, err := blockchain.InsertChain(types.Blocks{block}) if err == nil { t.Fatal("block imported without errors") @@ -361,9 +360,9 @@ func TestStateProcessorErrors(t *testing.T) { // valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently // valid to be considered for import: // - valid pow (fake), ancestry, difficulty, gaslimit etc -func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block { +func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig, isPOW bool) *types.Block { difficulty := big.NewInt(0) - if !config.TerminalTotalDifficultyPassed { + if isPOW { fakeChainReader := newChainMaker(nil, config, engine) difficulty = engine.CalcDifficulty(fakeChainReader, parent.Time()+10, &types.Header{ Number: parent.Number(), @@ -441,25 +440,22 @@ var ( func TestProcessVerkle(t *testing.T) { var ( config = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - Ethash: new(params.EthashConfig), - ShanghaiTime: u64(0), - VerkleTime: u64(0), - TerminalTotalDifficulty: common.Big0, - TerminalTotalDifficultyPassed: true, - // TODO uncomment when proof generation is merged - // ProofInBlocks: true, + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + Ethash: new(params.EthashConfig), + ShanghaiTime: u64(0), + VerkleTime: u64(0), + TerminalTotalDifficulty: common.Big0, } signer = types.LatestSigner(config) testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 35d6393fba0e..0e2fd52b14cf 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -919,7 +919,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address()) interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct) interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct) - interpreter.evm.StateDB.Selfdestruct6780(scope.Contract.Address()) + interpreter.evm.StateDB.SelfDestruct6780(scope.Contract.Address()) if tracer := interpreter.evm.Config.Tracer; tracer != nil { if tracer.OnEnter != nil { tracer.OnEnter(interpreter.evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig()) diff --git a/core/vm/interface.go b/core/vm/interface.go index 5f426435650d..9229f4d2cd95 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -33,8 +33,8 @@ type StateDB interface { CreateAccount(common.Address) CreateContract(common.Address) - SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) - AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) + SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int + AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int GetBalance(common.Address) *uint256.Int GetNonce(common.Address) uint64 @@ -51,16 +51,21 @@ type StateDB interface { GetCommittedState(common.Address, common.Hash) common.Hash GetState(common.Address, common.Hash) common.Hash - SetState(common.Address, common.Hash, common.Hash) + SetState(common.Address, common.Hash, common.Hash) common.Hash GetStorageRoot(addr common.Address) common.Hash GetTransientState(addr common.Address, key common.Hash) common.Hash SetTransientState(addr common.Address, key, value common.Hash) - SelfDestruct(common.Address) + SelfDestruct(common.Address) uint256.Int HasSelfDestructed(common.Address) bool - Selfdestruct6780(common.Address) + // SelfDestruct6780 is post-EIP6780 selfdestruct, which means that it's a + // send-all-to-beneficiary, unless the contract was created in this same + // transaction, in which case it will be destructed. + // This method returns the prior balance, along with a boolean which is + // true iff the object was indeed destructed. + 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. @@ -90,6 +95,9 @@ type StateDB interface { AddPreimage(common.Hash, []byte) Witness() *stateless.Witness + + // Finalise must be invoked at the end of a transaction + Finalise(bool) } // CallContext provides a basic interface for the EVM calling conventions. The EVM diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index f83ed682cd13..2ad991ee41f3 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -61,27 +61,26 @@ func setDefaults(cfg *Config) { cancunTime = uint64(0) ) cfg.ChainConfig = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: new(big.Int), - DAOForkBlock: new(big.Int), - DAOForkSupport: false, - EIP150Block: new(big.Int), - EIP155Block: new(big.Int), - EIP158Block: new(big.Int), - ByzantiumBlock: new(big.Int), - ConstantinopleBlock: new(big.Int), - PetersburgBlock: new(big.Int), - IstanbulBlock: new(big.Int), - MuirGlacierBlock: new(big.Int), - BerlinBlock: new(big.Int), - LondonBlock: new(big.Int), - ArrowGlacierBlock: nil, - GrayGlacierBlock: nil, - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - MergeNetsplitBlock: nil, - ShanghaiTime: &shanghaiTime, - CancunTime: &cancunTime} + ChainID: big.NewInt(1), + HomesteadBlock: new(big.Int), + DAOForkBlock: new(big.Int), + DAOForkSupport: false, + EIP150Block: new(big.Int), + EIP155Block: new(big.Int), + EIP158Block: new(big.Int), + ByzantiumBlock: new(big.Int), + ConstantinopleBlock: new(big.Int), + PetersburgBlock: new(big.Int), + IstanbulBlock: new(big.Int), + MuirGlacierBlock: new(big.Int), + BerlinBlock: new(big.Int), + LondonBlock: new(big.Int), + ArrowGlacierBlock: nil, + GrayGlacierBlock: nil, + TerminalTotalDifficulty: big.NewInt(0), + MergeNetsplitBlock: nil, + ShanghaiTime: &shanghaiTime, + CancunTime: &cancunTime} } if cfg.Difficulty == nil { cfg.Difficulty = new(big.Int) @@ -109,10 +108,7 @@ func setDefaults(cfg *Config) { if cfg.BlobBaseFee == nil { cfg.BlobBaseFee = big.NewInt(params.BlobTxMinBlobGasprice) } - // Merge indicators - if t := cfg.ChainConfig.ShanghaiTime; cfg.ChainConfig.TerminalTotalDifficultyPassed || (t != nil && *t == 0) { - cfg.Random = &(common.Hash{}) - } + cfg.Random = &(common.Hash{}) } // Execute executes the code using the input as call data during the execution. diff --git a/crypto/bn256/gnark/g1.go b/crypto/bn256/gnark/g1.go new file mode 100644 index 000000000000..2f933dd53601 --- /dev/null +++ b/crypto/bn256/gnark/g1.go @@ -0,0 +1,51 @@ +package bn256 + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bn254" +) + +// G1 is the affine representation of a G1 group element. +// +// Since this code is used for precompiles, using Jacobian +// points are not beneficial because there are no intermediate +// points to allow us to save on inversions. +// +// Note: We also use this struct so that we can conform to the existing API +// that the precompiles want. +type G1 struct { + inner bn254.G1Affine +} + +// Add adds `a` and `b` together, storing the result in `g` +func (g *G1) Add(a, b *G1) { + g.inner.Add(&a.inner, &b.inner) +} + +// ScalarMult computes the scalar multiplication between `a` and +// `scalar`, storing the result in `g` +func (g *G1) ScalarMult(a *G1, scalar *big.Int) { + g.inner.ScalarMultiplication(&a.inner, scalar) +} + +// Unmarshal deserializes `buf` into `g` +// +// Note: whether the deserialization is of a compressed +// or an uncompressed point, is encoded in the bytes. +// +// For our purpose, the point will always be serialized +// as uncompressed, ie 64 bytes. +// +// This method also checks whether the point is on the +// curve and in the prime order subgroup. +func (g *G1) Unmarshal(buf []byte) (int, error) { + return g.inner.SetBytes(buf) +} + +// Marshal serializes the point into a byte slice. +// +// Note: The point is serialized as uncompressed. +func (p *G1) Marshal() []byte { + return p.inner.Marshal() +} diff --git a/crypto/bn256/gnark/g2.go b/crypto/bn256/gnark/g2.go new file mode 100644 index 000000000000..205373a59194 --- /dev/null +++ b/crypto/bn256/gnark/g2.go @@ -0,0 +1,38 @@ +package bn256 + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254" +) + +// G2 is the affine representation of a G2 group element. +// +// Since this code is used for precompiles, using Jacobian +// points are not beneficial because there are no intermediate +// points and G2 in particular is only used for the pairing input. +// +// Note: We also use this struct so that we can conform to the existing API +// that the precompiles want. +type G2 struct { + inner bn254.G2Affine +} + +// Unmarshal deserializes `buf` into `g` +// +// Note: whether the deserialization is of a compressed +// or an uncompressed point, is encoded in the bytes. +// +// For our purpose, the point will always be serialized +// as uncompressed, ie 128 bytes. +// +// This method also checks whether the point is on the +// curve and in the prime order subgroup. +func (g *G2) Unmarshal(buf []byte) (int, error) { + return g.inner.SetBytes(buf) +} + +// Marshal serializes the point into a byte slice. +// +// Note: The point is serialized as uncompressed. +func (g *G2) Marshal() []byte { + return g.inner.Marshal() +} diff --git a/crypto/bn256/gnark/gt.go b/crypto/bn256/gnark/gt.go new file mode 100644 index 000000000000..c30022c5f898 --- /dev/null +++ b/crypto/bn256/gnark/gt.go @@ -0,0 +1,65 @@ +package bn256 + +import ( + "fmt" + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bn254" +) + +// GT is the affine representation of a GT field element. +// +// Note: GT is not explicitly used in mainline code. +// It is needed for fuzzing. +type GT struct { + inner bn254.GT +} + +// Pair compute the optimal Ate pairing between a G1 and +// G2 element. +// +// Note: This method is not explicitly used in mainline code. +// It is needed for fuzzing. It should also be noted, +// that the output of this function may not match other +func Pair(a_ *G1, b_ *G2) *GT { + a := a_.inner + b := b_.inner + + pairingOutput, err := bn254.Pair([]bn254.G1Affine{a}, []bn254.G2Affine{b}) + + if err != nil { + // Since this method is only called during fuzzing, it is okay to panic here. + // We do not return an error to match the interface of the other bn256 libraries. + panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err)) + } + + return >{ + inner: pairingOutput, + } +} + +// Unmarshal deserializes `buf` into `g` +// +// Note: This method is not explicitly used in mainline code. +// It is needed for fuzzing. +func (g *GT) Unmarshal(buf []byte) error { + return g.inner.SetBytes(buf) +} + +// Marshal serializes the point into a byte slice. +// +// Note: This method is not explicitly used in mainline code. +// It is needed for fuzzing. +func (g *GT) Marshal() []byte { + bytes := g.inner.Bytes() + return bytes[:] +} + +// Exp raises `base` to the power of `exponent` +// +// Note: This method is not explicitly used in mainline code. +// It is needed for fuzzing. +func (g *GT) Exp(base GT, exponent *big.Int) *GT { + g.inner.Exp(base.inner, exponent) + return g +} diff --git a/crypto/bn256/gnark/pairing.go b/crypto/bn256/gnark/pairing.go new file mode 100644 index 000000000000..39e8a657f466 --- /dev/null +++ b/crypto/bn256/gnark/pairing.go @@ -0,0 +1,73 @@ +package bn256 + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254" +) + +// Computes the following relation: ∏ᵢ e(Pᵢ, Qᵢ) =? 1 +// +// To explain why gnark returns a (bool, error): +// +// - If the function `e` does not return a result then internally +// an error is returned. +// - If `e` returns a result, then error will be nil, +// but if this value is not `1` then the boolean value will be false +// +// We therefore check for an error, and return false if its non-nil and +// then return the value of the boolean if not. +func PairingCheck(a_ []*G1, b_ []*G2) bool { + a := getInnerG1s(a_) + b := getInnerG2s(b_) + + // Assume that len(a) == len(b) + // + // The pairing function will return + // false, if this is not the case. + size := len(a) + + // Check if input is empty -- gnark will + // return false on an empty input, however + // the ossified behavior is to return true + // on an empty input, so we add this if statement. + if size == 0 { + return true + } + + ok, err := bn254.PairingCheck(a, b) + if err != nil { + return false + } + return ok +} + +// getInnerG1s gets the inner gnark G1 elements. +// +// These methods are used for two reasons: +// +// - We use a new type `G1`, so we need to convert from +// []*G1 to []*bn254.G1Affine +// - The gnark API accepts slices of values and not slices of +// pointers to values, so we need to return []bn254.G1Affine +// instead of []*bn254.G1Affine. +func getInnerG1s(pointerSlice []*G1) []bn254.G1Affine { + gnarkValues := make([]bn254.G1Affine, 0, len(pointerSlice)) + for _, ptr := range pointerSlice { + if ptr != nil { + gnarkValues = append(gnarkValues, ptr.inner) + } + } + return gnarkValues +} + +// getInnerG2s gets the inner gnark G2 elements. +// +// The rationale for this method is the same as `getInnerG1s`. +func getInnerG2s(pointerSlice []*G2) []bn254.G2Affine { + gnarkValues := make([]bn254.G2Affine, 0, len(pointerSlice)) + for _, ptr := range pointerSlice { + if ptr != nil { + gnarkValues = append(gnarkValues, ptr.inner) + } + } + return gnarkValues +} diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index 74a5a66ed1c9..7bb31329c6ce 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -66,7 +66,6 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) { engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker())) if merged { config.TerminalTotalDifficulty = common.Big0 - config.TerminalTotalDifficultyPassed = true engine = beaconConsensus.NewFaker() } genesis := &core.Genesis{ diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index c781a639408a..c325e5010c4d 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -18,7 +18,7 @@ package ethconfig import ( - "errors" + "fmt" "time" "github.com/ethereum/go-ethereum/common" @@ -162,10 +162,8 @@ type Config struct { // Clique is allowed for now to live standalone, but ethash is forbidden and can // only exist on already merged networks. func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) { - // Geth v1.14.0 dropped support for non-merged networks in any consensus - // mode. If such a network is requested, reject startup. - if !config.TerminalTotalDifficultyPassed { - return nil, errors.New("only PoS networks are supported, please transition old ones with Geth v1.13.x") + if config.TerminalTotalDifficulty == nil { + return nil, fmt.Errorf("only PoS networks are supported, please transition old ones with Geth v1.13.x") } // Wrap previously supported consensus engines into their post-merge counterpart if config.Clique != nil { diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index fc82b42947f3..faf360cc53e3 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -75,27 +75,26 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int, if shanghai { config = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - MergeNetsplitBlock: big.NewInt(0), - ShanghaiTime: u64(0), - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - Ethash: new(params.EthashConfig), + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: big.NewInt(0), + ShanghaiTime: u64(0), + TerminalTotalDifficulty: big.NewInt(0), + Ethash: new(params.EthashConfig), } engine = beacon.NewFaker() } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 5b6945f54f0c..7d8191c25bd6 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -1018,7 +1018,6 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor } // The actual TxContext will be created as part of ApplyTransactionWithEVM. vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true}) - statedb.SetLogger(tracer.Hooks) // Define a meaningful timeout of a single transaction trace if config.Timeout != nil { diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index d21e589f3dfc..5b9c80959662 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -29,6 +29,7 @@ import ( "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/crypto" @@ -116,21 +117,23 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { 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) - state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) + st = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) ) - state.Close() + st.Close() tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config) if err != nil { t.Fatalf("failed to create call tracer: %v", err) } - - state.StateDB.SetLogger(tracer.Hooks) + 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, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) + evm := vm.NewEVM(context, core.NewEVMTxContext(msg), 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 { @@ -349,7 +352,7 @@ func TestInternals(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - state := tests.MakePreState(rawdb.NewMemoryDatabase(), + st := tests.MakePreState(rawdb.NewMemoryDatabase(), types.GenesisAlloc{ to: types.Account{ Code: tc.code, @@ -358,8 +361,13 @@ func TestInternals(t *testing.T) { Balance: big.NewInt(500000000000000), }, }, false, rawdb.HashScheme) - defer state.Close() - state.StateDB.SetLogger(tc.tracer.Hooks) + defer st.Close() + + logState := vm.StateDB(st.StateDB) + if hooks := tc.tracer.Hooks; hooks != nil { + logState = state.NewHookedState(st.StateDB, hooks) + } + tx, err := types.SignNewTx(key, signer, &types.LegacyTx{ To: &to, Value: big.NewInt(0), @@ -373,7 +381,7 @@ func TestInternals(t *testing.T) { Origin: origin, GasPrice: tx.GasPrice(), } - evm := vm.NewEVM(context, txContext, state.StateDB, config, vm.Config{Tracer: tc.tracer.Hooks}) + evm := vm.NewEVM(context, txContext, logState, config, vm.Config{Tracer: tc.tracer.Hooks}) msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0)) if err != nil { t.Fatalf("test %v: failed to create message: %v", tc.name, err) diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go index 7a6e1751e87d..0ec3c367bc5b 100644 --- a/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -94,7 +94,6 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string return fmt.Errorf("failed to create call tracer: %v", err) } - state.StateDB.SetLogger(tracer.Hooks) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) if err != nil { return fmt.Errorf("failed to prepare transaction for tracing: %v", err) diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 90f59225dfd0..c6cf10a48346 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -102,7 +102,6 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } - state.StateDB.SetLogger(tracer.Hooks) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) diff --git a/eth/tracers/internal/tracetest/supply_test.go b/eth/tracers/internal/tracetest/supply_test.go index 2cddcae67d8a..2391add91b95 100644 --- a/eth/tracers/internal/tracetest/supply_test.go +++ b/eth/tracers/internal/tracetest/supply_test.go @@ -597,6 +597,7 @@ func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockG } func compareAsJSON(t *testing.T, expected interface{}, actual interface{}) { + t.Helper() want, err := json.Marshal(expected) if err != nil { t.Fatalf("failed to marshal expected value to JSON: %v", err) @@ -608,6 +609,6 @@ func compareAsJSON(t *testing.T, expected interface{}, actual interface{}) { } if !bytes.Equal(want, have) { - t.Fatalf("incorrect supply info: expected %s, got %s", string(want), string(have)) + t.Fatalf("incorrect supply info:\nwant %s\nhave %s", string(want), string(have)) } } diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json b/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json index b974151c1b36..05da3b42e194 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json @@ -41,8 +41,7 @@ "grayGlacierBlock": 0, "shanghaiTime": 0, "cancunTime": 0, - "terminalTotalDifficulty": 0, - "terminalTotalDifficultyPassed": true + "terminalTotalDifficulty": 0 } }, "context": { diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json index 89f642db20bf..b8b20e1b8c63 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json @@ -61,7 +61,6 @@ "berlinBlock": 4460644, "londonBlock": 5062605, "terminalTotalDifficulty": 10790000, - "terminalTotalDifficultyPassed": true, "clique": { "period": 15, "epoch": 30000 @@ -185,4 +184,4 @@ "type": "call" } ] -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json index cef0c1c5a80a..30991edafb2c 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json @@ -59,7 +59,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json index 0ae76e92f9bb..cdb0dda5f82b 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json @@ -116,7 +116,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/frontier_create_outofstorage.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/frontier_create_outofstorage.json index 049f24d9328f..e562affb1576 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/frontier_create_outofstorage.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/frontier_create_outofstorage.json @@ -60,7 +60,6 @@ "grayGlacierBlock": 15050000, "shanghaiTime": 1681338455, "terminalTotalDifficulty": 7797655526461000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, @@ -186,4 +185,4 @@ "value": "0x0", "type": "CREATE" } -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json index 5cc3013f8076..43d6be2be9c9 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json @@ -281,7 +281,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json index c931ed63fc37..3434dd31031d 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json @@ -149,7 +149,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json index 42fc87255480..814189dc6b35 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json @@ -84,7 +84,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json index 5300d341b824..c00f0831599e 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json @@ -45,7 +45,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_failed.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_failed.json index d5c2f864c168..293575a98910 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_failed.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_failed.json @@ -119,7 +119,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json index 1267160d1338..aba652ede631 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json @@ -57,7 +57,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json index 38d96a6bd08e..ed518faf5ed3 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json @@ -59,7 +59,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json index 444eba450bec..f8adbabf6377 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json @@ -41,8 +41,7 @@ "grayGlacierBlock": 0, "shanghaiTime": 0, "cancunTime": 0, - "terminalTotalDifficulty": 0, - "terminalTotalDifficultyPassed": true + "terminalTotalDifficulty": 0 } }, "context": { diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json index b013d520c1ad..489a1ae6b538 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json @@ -38,7 +38,6 @@ "grayGlacierBlock": 0, "shanghaiTime": 0, "terminalTotalDifficulty": 0, - "terminalTotalDifficultyPassed": true, "isDev": true } }, @@ -59,4 +58,4 @@ "balance": "0x8ac7230489e80000" } } -} \ No newline at end of file +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_existing_contract.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_existing_contract.json index 64a3b16cb1fe..abbc104f3282 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_existing_contract.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_existing_contract.json @@ -49,7 +49,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json index ae7f7e97f5a9..b5bccf7bd05d 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json @@ -55,7 +55,6 @@ "londonBlock": 12965000, "arrowGlacierBlock": 13773000, "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, "ethash": {} } }, diff --git a/eth/tracers/internal/tracetest/util.go b/eth/tracers/internal/tracetest/util.go index a74a96f8a489..abc2699498d4 100644 --- a/eth/tracers/internal/tracetest/util.go +++ b/eth/tracers/internal/tracetest/util.go @@ -47,6 +47,11 @@ func (c *callContext) toBlockContext(genesis *core.Genesis) vm.BlockContext { if genesis.Config.IsLondon(context.BlockNumber) { context.BaseFee = (*big.Int)(c.BaseFee) } + + if genesis.Config.TerminalTotalDifficulty != nil && genesis.Config.TerminalTotalDifficulty.Sign() == 0 { + context.Random = &genesis.Mixhash + } + if genesis.ExcessBlobGas != nil && genesis.BlobGasUsed != nil { excessBlobGas := eip4844.CalcExcessBlobGas(*genesis.ExcessBlobGas, *genesis.BlobGasUsed) context.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas) diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index 137608f8847d..fb1a0154e311 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -49,9 +49,11 @@ type dummyStatedb struct { state.StateDB } -func (*dummyStatedb) GetRefund() uint64 { return 1337 } -func (*dummyStatedb) GetState(_ common.Address, _ common.Hash) common.Hash { return common.Hash{} } -func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) {} +func (*dummyStatedb) GetRefund() uint64 { return 1337 } +func (*dummyStatedb) GetState(_ common.Address, _ common.Hash) common.Hash { return common.Hash{} } +func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) common.Hash { + return common.Hash{} +} func TestStoreCapture(t *testing.T) { var ( diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go index a6be589a0f12..231170c273e2 100644 --- a/graphql/graphql_test.go +++ b/graphql/graphql_test.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "io" + "math" "math/big" "net/http" "strings" @@ -459,13 +460,14 @@ func newGQLService(t *testing.T, stack *node.Node, shanghai bool, gspec *core.Ge var engine consensus.Engine = ethash.NewFaker() if shanghai { engine = beacon.NewFaker() - chainCfg := gspec.Config - chainCfg.TerminalTotalDifficultyPassed = true - chainCfg.TerminalTotalDifficulty = common.Big0 + gspec.Config.TerminalTotalDifficulty = common.Big0 // GenerateChain will increment timestamps by 10. // Shanghai upgrade at block 1. shanghaiTime := uint64(5) - chainCfg.ShanghaiTime = &shanghaiTime + gspec.Config.ShanghaiTime = &shanghaiTime + } else { + // set an arbitrary large ttd as chains are required to be known to be merged + gspec.Config.TerminalTotalDifficulty = big.NewInt(math.MaxInt64) } ethBackend, err := eth.New(stack, ethConf) if err != nil { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index a1f4304690a4..10d79c85ae06 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1209,11 +1209,16 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s if precompiles != nil { evm.SetPrecompiles(precompiles) } - - return applyMessageWithEVM(ctx, evm, msg, state, timeout, gp) + res, err := applyMessageWithEVM(ctx, evm, msg, timeout, gp) + // If an internal state error occurred, let that have precedence. Otherwise, + // a "trie root missing" type of error will masquerade as e.g. "insufficient gas" + if err := state.Error(); err != nil { + return nil, err + } + return res, err } -func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, state *state.StateDB, timeout time.Duration, gp *core.GasPool) (*core.ExecutionResult, error) { +func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, timeout time.Duration, gp *core.GasPool) (*core.ExecutionResult, error) { // Wait for the context to be done and cancel the evm. Even if the // EVM has finished, cancelling may be done (repeatedly) go func() { @@ -1223,9 +1228,6 @@ func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, st // Execute the message. result, err := core.ApplyMessage(evm, msg, gp) - if err := state.Error(); err != nil { - return nil, err - } // If the timer caused an abort, return an appropriate error message if evm.Cancelled() { diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index a27f1f536dba..93b1c0855112 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -2192,6 +2192,7 @@ func TestSimulateV1(t *testing.T) { t.Fatalf("failed to unmarshal result: %v", err) } if !reflect.DeepEqual(have, tc.want) { + t.Log(string(resBytes)) t.Errorf("test %s, result mismatch, have\n%v\n, want\n%v\n", tc.name, have, tc.want) } }) diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index 4371a4246480..81b4633d42cf 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -187,7 +187,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, } evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, sim.state, sim.chainConfig, *vmConfig) ) - sim.state.SetLogger(tracer.Hooks()) + var tracingStateDB = vm.StateDB(sim.state) + if hooks := tracer.Hooks(); hooks != nil { + tracingStateDB = state.NewHookedState(sim.state, hooks) + } // It is possible to override precompiles with EVM bytecode, or // move them to another address. if precompiles != nil { @@ -205,8 +208,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, tracer.reset(tx.Hash(), uint(i)) // EoA check is always skipped, even in validation mode. msg := call.ToMessage(header.BaseFee, !sim.validate, true) - evm.Reset(core.NewEVMTxContext(msg), sim.state) - result, err := applyMessageWithEVM(ctx, evm, msg, sim.state, timeout, sim.gp) + evm.Reset(core.NewEVMTxContext(msg), tracingStateDB) + result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp) if err != nil { txErr := txValidationError(err) return nil, nil, txErr @@ -214,7 +217,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, // Update the state with pending changes. var root []byte if sim.chainConfig.IsByzantium(blockContext.BlockNumber) { - sim.state.Finalise(true) + tracingStateDB.Finalise(true) } else { root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes() } diff --git a/params/config.go b/params/config.go index cac948bf2df5..9b3b92484ab2 100644 --- a/params/config.go +++ b/params/config.go @@ -18,6 +18,7 @@ package params import ( "fmt" + "math" "math/big" "github.com/ethereum/go-ethereum/common" @@ -38,249 +39,240 @@ var ( // MainnetChainConfig is the chain parameters to run a node on the main network. MainnetChainConfig = &ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(1_150_000), - DAOForkBlock: big.NewInt(1_920_000), - DAOForkSupport: true, - EIP150Block: big.NewInt(2_463_000), - EIP155Block: big.NewInt(2_675_000), - EIP158Block: big.NewInt(2_675_000), - ByzantiumBlock: big.NewInt(4_370_000), - ConstantinopleBlock: big.NewInt(7_280_000), - PetersburgBlock: big.NewInt(7_280_000), - IstanbulBlock: big.NewInt(9_069_000), - MuirGlacierBlock: big.NewInt(9_200_000), - BerlinBlock: big.NewInt(12_244_000), - LondonBlock: big.NewInt(12_965_000), - ArrowGlacierBlock: big.NewInt(13_773_000), - GrayGlacierBlock: big.NewInt(15_050_000), - TerminalTotalDifficulty: MainnetTerminalTotalDifficulty, // 58_750_000_000_000_000_000_000 - TerminalTotalDifficultyPassed: true, - ShanghaiTime: newUint64(1681338455), - CancunTime: newUint64(1710338135), - DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"), - Ethash: new(EthashConfig), + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(1_150_000), + DAOForkBlock: big.NewInt(1_920_000), + DAOForkSupport: true, + EIP150Block: big.NewInt(2_463_000), + EIP155Block: big.NewInt(2_675_000), + EIP158Block: big.NewInt(2_675_000), + ByzantiumBlock: big.NewInt(4_370_000), + ConstantinopleBlock: big.NewInt(7_280_000), + PetersburgBlock: big.NewInt(7_280_000), + IstanbulBlock: big.NewInt(9_069_000), + MuirGlacierBlock: big.NewInt(9_200_000), + BerlinBlock: big.NewInt(12_244_000), + LondonBlock: big.NewInt(12_965_000), + ArrowGlacierBlock: big.NewInt(13_773_000), + GrayGlacierBlock: big.NewInt(15_050_000), + TerminalTotalDifficulty: MainnetTerminalTotalDifficulty, // 58_750_000_000_000_000_000_000 + ShanghaiTime: newUint64(1681338455), + CancunTime: newUint64(1710338135), + DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"), + Ethash: new(EthashConfig), } // HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network. HoleskyChainConfig = &ChainConfig{ - ChainID: big.NewInt(17000), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: nil, - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: nil, - GrayGlacierBlock: nil, - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - MergeNetsplitBlock: nil, - ShanghaiTime: newUint64(1696000704), - CancunTime: newUint64(1707305664), - Ethash: new(EthashConfig), + ChainID: big.NewInt(17000), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: nil, + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: nil, + GrayGlacierBlock: nil, + TerminalTotalDifficulty: big.NewInt(0), + MergeNetsplitBlock: nil, + ShanghaiTime: newUint64(1696000704), + CancunTime: newUint64(1707305664), + Ethash: new(EthashConfig), } // SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network. SepoliaChainConfig = &ChainConfig{ - ChainID: big.NewInt(11155111), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: nil, - GrayGlacierBlock: nil, - TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000), - TerminalTotalDifficultyPassed: true, - MergeNetsplitBlock: big.NewInt(1735371), - ShanghaiTime: newUint64(1677557088), - CancunTime: newUint64(1706655072), - Ethash: new(EthashConfig), + ChainID: big.NewInt(11155111), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: nil, + GrayGlacierBlock: nil, + TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000), + MergeNetsplitBlock: big.NewInt(1735371), + ShanghaiTime: newUint64(1677557088), + CancunTime: newUint64(1706655072), + Ethash: new(EthashConfig), } // AllEthashProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Ethash consensus. AllEthashProtocolChanges = &ChainConfig{ - ChainID: big.NewInt(1337), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: false, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - MergeNetsplitBlock: nil, - ShanghaiTime: nil, - CancunTime: nil, - PragueTime: nil, - VerkleTime: nil, - TerminalTotalDifficulty: nil, - TerminalTotalDifficultyPassed: true, - Ethash: new(EthashConfig), - Clique: nil, + ChainID: big.NewInt(1337), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(math.MaxInt64), + MergeNetsplitBlock: nil, + ShanghaiTime: nil, + CancunTime: nil, + PragueTime: nil, + VerkleTime: nil, + Ethash: new(EthashConfig), + Clique: nil, } AllDevChainProtocolChanges = &ChainConfig{ - ChainID: big.NewInt(1337), - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - ShanghaiTime: newUint64(0), - CancunTime: newUint64(0), - PragueTime: newUint64(0), - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, + ChainID: big.NewInt(1337), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + ShanghaiTime: newUint64(0), + CancunTime: newUint64(0), + TerminalTotalDifficulty: big.NewInt(0), + PragueTime: newUint64(0), } // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. AllCliqueProtocolChanges = &ChainConfig{ - ChainID: big.NewInt(1337), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: false, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: nil, - GrayGlacierBlock: nil, - MergeNetsplitBlock: nil, - ShanghaiTime: nil, - CancunTime: nil, - PragueTime: nil, - VerkleTime: nil, - TerminalTotalDifficulty: nil, - TerminalTotalDifficultyPassed: false, - Ethash: nil, - Clique: &CliqueConfig{Period: 0, Epoch: 30000}, + ChainID: big.NewInt(1337), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: nil, + GrayGlacierBlock: nil, + MergeNetsplitBlock: nil, + ShanghaiTime: nil, + CancunTime: nil, + PragueTime: nil, + VerkleTime: nil, + TerminalTotalDifficulty: big.NewInt(math.MaxInt64), + Ethash: nil, + Clique: &CliqueConfig{Period: 0, Epoch: 30000}, } // TestChainConfig contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers for testing purposes. TestChainConfig = &ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: false, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - MergeNetsplitBlock: nil, - ShanghaiTime: nil, - CancunTime: nil, - PragueTime: nil, - VerkleTime: nil, - TerminalTotalDifficulty: nil, - TerminalTotalDifficultyPassed: false, - Ethash: new(EthashConfig), - Clique: nil, + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: nil, + ShanghaiTime: nil, + CancunTime: nil, + PragueTime: nil, + VerkleTime: nil, + TerminalTotalDifficulty: big.NewInt(math.MaxInt64), + Ethash: new(EthashConfig), + Clique: nil, } // MergedTestChainConfig contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers for testing purposes. MergedTestChainConfig = &ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: false, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - MergeNetsplitBlock: big.NewInt(0), - ShanghaiTime: newUint64(0), - CancunTime: newUint64(0), - PragueTime: newUint64(0), - VerkleTime: nil, - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - Ethash: new(EthashConfig), - Clique: nil, + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: big.NewInt(0), + ShanghaiTime: newUint64(0), + CancunTime: newUint64(0), + PragueTime: newUint64(0), + VerkleTime: nil, + TerminalTotalDifficulty: big.NewInt(0), + Ethash: new(EthashConfig), + Clique: nil, } // NonActivatedConfig defines the chain configuration without activating // any protocol change (EIPs). NonActivatedConfig = &ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: nil, - DAOForkBlock: nil, - DAOForkSupport: false, - EIP150Block: nil, - EIP155Block: nil, - EIP158Block: nil, - ByzantiumBlock: nil, - ConstantinopleBlock: nil, - PetersburgBlock: nil, - IstanbulBlock: nil, - MuirGlacierBlock: nil, - BerlinBlock: nil, - LondonBlock: nil, - ArrowGlacierBlock: nil, - GrayGlacierBlock: nil, - MergeNetsplitBlock: nil, - ShanghaiTime: nil, - CancunTime: nil, - PragueTime: nil, - VerkleTime: nil, - TerminalTotalDifficulty: nil, - TerminalTotalDifficultyPassed: false, - Ethash: new(EthashConfig), - Clique: nil, + ChainID: big.NewInt(1), + HomesteadBlock: nil, + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: nil, + EIP155Block: nil, + EIP158Block: nil, + ByzantiumBlock: nil, + ConstantinopleBlock: nil, + PetersburgBlock: nil, + IstanbulBlock: nil, + MuirGlacierBlock: nil, + BerlinBlock: nil, + LondonBlock: nil, + ArrowGlacierBlock: nil, + GrayGlacierBlock: nil, + MergeNetsplitBlock: nil, + ShanghaiTime: nil, + CancunTime: nil, + PragueTime: nil, + VerkleTime: nil, + TerminalTotalDifficulty: big.NewInt(math.MaxInt64), + Ethash: new(EthashConfig), + Clique: nil, } TestRules = TestChainConfig.Rules(new(big.Int), false, 0) ) @@ -332,13 +324,6 @@ type ChainConfig struct { // the network that triggers the consensus upgrade. TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` - // TerminalTotalDifficultyPassed is a flag specifying that the network already - // passed the terminal total difficulty. Its purpose is to disable legacy sync - // even without having seen the TTD locally (safer long term). - // - // TODO(karalabe): Drop this field eventually (always assuming PoS mode) - TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"` - DepositContractAddress common.Address `json:"depositContractAddress,omitempty"` // Various consensus engines @@ -377,21 +362,9 @@ func (c *ChainConfig) Description() string { banner += fmt.Sprintf("Chain ID: %v (%s)\n", c.ChainID, network) switch { case c.Ethash != nil: - if c.TerminalTotalDifficulty == nil { - banner += "Consensus: Ethash (proof-of-work)\n" - } else if !c.TerminalTotalDifficultyPassed { - banner += "Consensus: Beacon (proof-of-stake), merging from Ethash (proof-of-work)\n" - } else { - banner += "Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work)\n" - } + banner += "Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work)\n" case c.Clique != nil: - if c.TerminalTotalDifficulty == nil { - banner += "Consensus: Clique (proof-of-authority)\n" - } else if !c.TerminalTotalDifficultyPassed { - banner += "Consensus: Beacon (proof-of-stake), merging from Clique (proof-of-authority)\n" - } else { - banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n" - } + banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n" default: banner += "Consensus: unknown\n" } @@ -426,17 +399,12 @@ func (c *ChainConfig) Description() string { banner += "\n" // Add a special section for the merge as it's non-obvious - if c.TerminalTotalDifficulty == nil { - banner += "The Merge is not yet available for this network!\n" - banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n" - } else { - banner += "Merge configured:\n" - banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n" - banner += fmt.Sprintf(" - Network known to be merged: %v\n", c.TerminalTotalDifficultyPassed) - banner += fmt.Sprintf(" - Total terminal difficulty: %v\n", c.TerminalTotalDifficulty) - if c.MergeNetsplitBlock != nil { - banner += fmt.Sprintf(" - Merge netsplit block: #%-8v\n", c.MergeNetsplitBlock) - } + banner += "Merge configured:\n" + banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n" + banner += " - Network known to be merged\n" + banner += fmt.Sprintf(" - Total terminal difficulty: %v\n", c.TerminalTotalDifficulty) + if c.MergeNetsplitBlock != nil { + banner += fmt.Sprintf(" - Merge netsplit block: #%-8v\n", c.MergeNetsplitBlock) } banner += "\n" diff --git a/tests/block_test_util.go b/tests/block_test_util.go index b0a31a69720b..77bf945e40e7 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -22,6 +22,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + stdmath "math" "math/big" "os" "reflect" @@ -129,6 +130,11 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t } // Commit genesis state gspec := t.genesis(config) + + // if ttd is not specified, set an arbitrary huge value + if gspec.Config.TerminalTotalDifficulty == nil { + gspec.Config.TerminalTotalDifficulty = big.NewInt(stdmath.MaxInt64) + } triedb := triedb.NewDatabase(db, tconf) gblock, err := gspec.Commit(db, triedb) if err != nil { diff --git a/tests/difficulty_test.go b/tests/difficulty_test.go index 03e14df7c4df..74ac28363bac 100644 --- a/tests/difficulty_test.go +++ b/tests/difficulty_test.go @@ -36,22 +36,21 @@ var ( } ropstenChainConfig = params.ChainConfig{ - ChainID: big.NewInt(3), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(10), - EIP158Block: big.NewInt(10), - ByzantiumBlock: big.NewInt(1_700_000), - ConstantinopleBlock: big.NewInt(4_230_000), - PetersburgBlock: big.NewInt(4_939_394), - IstanbulBlock: big.NewInt(6_485_846), - MuirGlacierBlock: big.NewInt(7_117_117), - BerlinBlock: big.NewInt(9_812_189), - LondonBlock: big.NewInt(10_499_401), - TerminalTotalDifficulty: new(big.Int).SetUint64(50_000_000_000_000_000), - TerminalTotalDifficultyPassed: true, + ChainID: big.NewInt(3), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(10), + EIP158Block: big.NewInt(10), + ByzantiumBlock: big.NewInt(1_700_000), + ConstantinopleBlock: big.NewInt(4_230_000), + PetersburgBlock: big.NewInt(4_939_394), + IstanbulBlock: big.NewInt(6_485_846), + MuirGlacierBlock: big.NewInt(7_117_117), + BerlinBlock: big.NewInt(9_812_189), + LondonBlock: big.NewInt(10_499_401), + TerminalTotalDifficulty: new(big.Int).SetUint64(50_000_000_000_000_000), } ) diff --git a/tests/fuzzers/bn256/bn256_fuzz.go b/tests/fuzzers/bn256/bn256_fuzz.go index 75f7d59deeef..4521f6b0dbca 100644 --- a/tests/fuzzers/bn256/bn256_fuzz.go +++ b/tests/fuzzers/bn256/bn256_fuzz.go @@ -22,12 +22,12 @@ import ( "io" "math/big" - "github.com/consensys/gnark-crypto/ecc/bn254" cloudflare "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" + gnark "github.com/ethereum/go-ethereum/crypto/bn256/gnark" google "github.com/ethereum/go-ethereum/crypto/bn256/google" ) -func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine) { +func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *gnark.G1) { _, xc, err := cloudflare.RandomG1(input) if err != nil { // insufficient input @@ -37,14 +37,14 @@ func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine) if _, err := xg.Unmarshal(xc.Marshal()); err != nil { panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err)) } - xs := new(bn254.G1Affine) - if err := xs.Unmarshal(xc.Marshal()); err != nil { + xs := new(gnark.G1) + if _, err := xs.Unmarshal(xc.Marshal()); err != nil { panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err)) } return xc, xg, xs } -func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine) { +func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *gnark.G2) { _, xc, err := cloudflare.RandomG2(input) if err != nil { // insufficient input @@ -54,14 +54,14 @@ func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine) if _, err := xg.Unmarshal(xc.Marshal()); err != nil { panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err)) } - xs := new(bn254.G2Affine) - if err := xs.Unmarshal(xc.Marshal()); err != nil { + xs := new(gnark.G2) + if _, err := xs.Unmarshal(xc.Marshal()); err != nil { panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err)) } return xc, xg, xs } -// fuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries. +// fuzzAdd fuzzes bn256 addition between the Google, Cloudflare and Gnark libraries. func fuzzAdd(data []byte) int { input := bytes.NewReader(data) xc, xg, xs := getG1Points(input) @@ -72,7 +72,7 @@ func fuzzAdd(data []byte) int { if yc == nil { return 0 } - // Ensure both libs can parse the second curve point + // Ensure libs can parse the second curve point // Add the two points and ensure they result in the same output rc := new(cloudflare.G1) rc.Add(xc, yc) @@ -80,9 +80,8 @@ func fuzzAdd(data []byte) int { rg := new(google.G1) rg.Add(xg, yg) - tmpX := new(bn254.G1Jac).FromAffine(xs) - tmpY := new(bn254.G1Jac).FromAffine(ys) - rs := new(bn254.G1Affine).FromJacobian(tmpX.AddAssign(tmpY)) + rs := new(gnark.G1) + rs.Add(xs, ys) if !bytes.Equal(rc.Marshal(), rg.Marshal()) { panic("add mismatch: cloudflare/google") @@ -94,8 +93,8 @@ func fuzzAdd(data []byte) int { return 1 } -// fuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare -// libraries. +// fuzzMul fuzzes bn256 scalar multiplication between the Google, Cloudflare +// and Gnark libraries. func fuzzMul(data []byte) int { input := bytes.NewReader(data) pc, pg, ps := getG1Points(input) @@ -122,15 +121,13 @@ func fuzzMul(data []byte) int { rg := new(google.G1) rg.ScalarMult(pg, new(big.Int).SetBytes(buf)) - rs := new(bn254.G1Jac) - psJac := new(bn254.G1Jac).FromAffine(ps) - rs.ScalarMultiplication(psJac, new(big.Int).SetBytes(buf)) - rsAffine := new(bn254.G1Affine).FromJacobian(rs) + rs := new(gnark.G1) + rs.ScalarMult(ps, new(big.Int).SetBytes(buf)) if !bytes.Equal(rc.Marshal(), rg.Marshal()) { panic("scalar mul mismatch: cloudflare/google") } - if !bytes.Equal(rc.Marshal(), rsAffine.Marshal()) { + if !bytes.Equal(rc.Marshal(), rs.Marshal()) { panic("scalar mul mismatch: cloudflare/gnark") } return 1 @@ -150,17 +147,26 @@ func fuzzPair(data []byte) int { // Pair the two points and ensure they result in the same output clPair := cloudflare.Pair(pc, tc).Marshal() gPair := google.Pair(pg, tg).Marshal() + sPair := gnark.Pair(ps, ts).Marshal() + if !bytes.Equal(clPair, gPair) { panic("pairing mismatch: cloudflare/google") } - cPair, err := bn254.Pair([]bn254.G1Affine{*ps}, []bn254.G2Affine{*ts}) - if err != nil { - panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err)) + + normalizedClPair := normalizeGTToGnark(clPair).Marshal() + if !bytes.Equal(normalizedClPair, sPair) { + panic("pairing mismatch: cloudflare/gnark") } - // gnark uses a different pairing algorithm which might produce - // different but also correct outputs, we need to scale the output by s + return 1 +} +// normalizeGTToGnark scales a Cloudflare/Google GT element by `s` +// so that it can be compared with a gnark GT point. +// +// For the definition of `s` see 3.5 in https://eprint.iacr.org/2015/192.pdf +func normalizeGTToGnark(cloudflareOrGoogleGT []byte) *gnark.GT { + // Compute s = 2*u(6*u^2 + 3*u + 1) u, _ := new(big.Int).SetString("0x44e992b44a6909f1", 0) u_exp2 := new(big.Int).Exp(u, big.NewInt(2), nil) // u^2 u_6_exp2 := new(big.Int).Mul(big.NewInt(6), u_exp2) // 6*u^2 @@ -170,14 +176,12 @@ func fuzzPair(data []byte) int { u_2 := new(big.Int).Mul(big.NewInt(2), u) // 2*u s := u_2.Mul(u_2, inner) // 2*u(6*u^2 + 3*u + 1) - gRes := new(bn254.GT) - if err := gRes.SetBytes(clPair); err != nil { + // Scale the Cloudflare/Google GT element by `s` + gRes := new(gnark.GT) + if err := gRes.Unmarshal(cloudflareOrGoogleGT); err != nil { panic(err) } gRes = gRes.Exp(*gRes, s) - if !bytes.Equal(cPair.Marshal(), gRes.Marshal()) { - panic("pairing mismatch: cloudflare/gnark") - } - return 1 + return gRes }