From 3f5751e6e663c99d021c4a030ce6eb97bf60acd8 Mon Sep 17 00:00:00 2001 From: Mita Date: Wed, 13 Mar 2024 20:04:04 +0100 Subject: [PATCH 01/13] Introducing OptimizedStack based on uint256 integers. --- go.mod | 2 + go.sum | 15 + state/runtime/evm/dispatch_table_test.go | 6 +- state/runtime/evm/evm_test.go | 3 +- state/runtime/evm/instructions.go | 486 ++++++-------- .../evm/instructions_benchmark_test.go | 233 +++++++ state/runtime/evm/instructions_test.go | 593 +++++++----------- state/runtime/evm/optimized_stack.go | 74 +++ state/runtime/evm/optimized_stack_test.go | 121 ++++ state/runtime/evm/state.go | 112 ++-- state/runtime/evm/state_test.go | 7 +- 11 files changed, 926 insertions(+), 726 deletions(-) create mode 100644 state/runtime/evm/instructions_benchmark_test.go create mode 100644 state/runtime/evm/optimized_stack.go create mode 100644 state/runtime/evm/optimized_stack_test.go diff --git a/go.mod b/go.mod index ae24fcccc7..0e159950e7 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,8 @@ require ( pgregory.net/rapid v1.1.0 ) +require github.com/holiman/uint256 v1.2.4 // indirect + require ( cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect diff --git a/go.sum b/go.sum index 62c7ce2986..2342890a53 100644 --- a/go.sum +++ b/go.sum @@ -92,9 +92,11 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -107,6 +109,7 @@ github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/P github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -178,6 +181,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -309,6 +313,8 @@ github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31 github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4= github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= @@ -336,6 +342,7 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -343,6 +350,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -425,6 +433,7 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -464,6 +473,7 @@ github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -493,6 +503,7 @@ github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= @@ -567,6 +578,7 @@ github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAjPbcMsODrTQUpJ02eNLUoxBg= github.com/secure-systems-lab/go-securesystemslib v0.7.0/go.mod h1:/2gYnlnHVQ6xeGtfIqFy7Do03K4cdCY0A/GlJLDKLHI= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -627,6 +639,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -652,6 +665,8 @@ github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4x github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= diff --git a/state/runtime/evm/dispatch_table_test.go b/state/runtime/evm/dispatch_table_test.go index a3dfe906a6..1efed0f376 100644 --- a/state/runtime/evm/dispatch_table_test.go +++ b/state/runtime/evm/dispatch_table_test.go @@ -25,10 +25,10 @@ func TestPushOpcodes(t *testing.T) { assert.False(t, s.stop) - res := s.pop().Bytes() - assert.Len(t, res, c) + v := s.pop() + assert.Len(t, v.Bytes(), c) - assert.True(t, bytes.HasPrefix(code[1:], res)) + assert.True(t, bytes.HasPrefix(code[1:], v.Bytes())) c++ } } diff --git a/state/runtime/evm/evm_test.go b/state/runtime/evm/evm_test.go index 6b20b48e29..1401de4a26 100644 --- a/state/runtime/evm/evm_test.go +++ b/state/runtime/evm/evm_test.go @@ -8,6 +8,7 @@ import ( "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/state/runtime/tracer" "github.com/0xPolygon/polygon-edge/types" + "github.com/holiman/uint256" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -422,7 +423,7 @@ func TestRunWithTracer(t *testing.T) { state.config = config // make sure stack, memory, and returnData are empty - state.stack = make([]*big.Int, 0) + state.stack.data = make([]uint256.Int, 0) state.memory = make([]byte, 0) state.returnData = make([]byte, 0) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 8fc6d3bb19..dfb490c58b 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -12,6 +12,7 @@ import ( "github.com/0xPolygon/polygon-edge/helper/keccak" "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" + "github.com/holiman/uint256" ) type instruction func(c *state) @@ -23,11 +24,39 @@ const ( ) var ( - zero = big.NewInt(0) - one = big.NewInt(1) - wordSize = big.NewInt(32) + zero = big.NewInt(0) + one = big.NewInt(1) + wordSize = big.NewInt(32) + wordSize256 = uint256.NewInt(32) ) +func equalOrOverflowsUint256(b *big.Int) bool { + return b.BitLen() > 8 +} + +var bufPool = sync.Pool{ + New: func() interface{} { + // Store pointer to avoid heap allocation in caller + // Please check SA6002 in StaticCheck for details + buf := make([]byte, 128) + + return &buf + }, +} + +var ( + _W = bits.UintSize + _S = _W / 8 +) + +func min(i, j uint64) uint64 { + if i < j { + return i + } + + return j +} + func (c *state) calculateGasForEIP2929(addr types.Address) uint64 { var gas uint64 if c.host.ContainsAccessListAddress(addr) { @@ -45,98 +74,49 @@ func opAdd(c *state) { a := c.pop() b := c.top() - b.Add(a, b) - toU256(b) + b.Add(&a, b) } func opMul(c *state) { a := c.pop() b := c.top() - b.Mul(a, b) - toU256(b) + b.Mul(&a, b) } func opSub(c *state) { a := c.pop() b := c.top() - b.Sub(a, b) - toU256(b) + b.Sub(&a, b) } func opDiv(c *state) { a := c.pop() b := c.top() - if b.Sign() == 0 { - // division by zero - b.Set(zero) - } else { - b.Div(a, b) - toU256(b) - } + b.Div(&a, b) } func opSDiv(c *state) { - a := to256(c.pop()) - b := to256(c.top()) + a := c.pop() + b := c.top() - if b.Sign() == 0 { - // division by zero - b.Set(zero) - } else { - neg := a.Sign() != b.Sign() - b.Div(a.Abs(a), b.Abs(b)) - if neg { - b.Neg(b) - } - toU256(b) - } + b.SDiv(&a, b) } func opMod(c *state) { a := c.pop() b := c.top() - if b.Sign() == 0 { - // division by zero - b.Set(zero) - } else { - b.Mod(a, b) - toU256(b) - } + b = b.Mod(&a, b) } func opSMod(c *state) { - a := to256(c.pop()) - b := to256(c.top()) - - if b.Sign() == 0 { - // division by zero - b.Set(zero) - } else { - neg := a.Sign() < 0 - b.Mod(a.Abs(a), b.Abs(b)) - if neg { - b.Neg(b) - } - toU256(b) - } -} - -var bigPool = sync.Pool{ - New: func() interface{} { - return new(big.Int) - }, -} - -func acquireBig() *big.Int { - return bigPool.Get().(*big.Int) -} + a := c.pop() + b := c.top() -func releaseBig(b *big.Int) { - bigPool.Put(b) + b.SMod(&a, b) } func opExp(c *state) { @@ -155,23 +135,7 @@ func opExp(c *state) { return } - z := acquireBig().Set(one) - - // https://www.programminglogic.com/fast-exponentiation-algorithms/ - for _, d := range y.Bits() { - for i := 0; i < _W; i++ { - if d&1 == 1 { - toU256(z.Mul(z, x)) - } - - d >>= 1 - - toU256(x.Mul(x, x)) - } - } - - y.Set(z) - releaseBig(z) + y = y.Exp(&x, y) } func opAddMod(c *state) { @@ -179,13 +143,10 @@ func opAddMod(c *state) { b := c.pop() z := c.top() - if z.Sign() == 0 { - // division by zero - z.Set(zero) + if z.IsZero() { + z.SetUint64(0) } else { - a = a.Add(a, b) - z = z.Mod(a, z) - toU256(z) + z.AddMod(&a, &b, z) } } @@ -194,13 +155,11 @@ func opMulMod(c *state) { b := c.pop() z := c.top() - if z.Sign() == 0 { + if z.IsZero() { // division by zero - z.Set(zero) + z.SetUint64(0) } else { - a = a.Mul(a, b) - z = z.Mod(a, z) - toU256(z) + z = z.MulMod(&a, &b, z) } } @@ -208,53 +167,42 @@ func opAnd(c *state) { a := c.pop() b := c.top() - b.And(a, b) + b.And(&a, b) } func opOr(c *state) { a := c.pop() b := c.top() - b.Or(a, b) + b.Or(&a, b) } func opXor(c *state) { a := c.pop() b := c.top() - b.Xor(a, b) + b.Xor(&a, b) } -var opByteMask = big.NewInt(255) - func opByte(c *state) { x := c.pop() y := c.top() - indx := x.Int64() - if indx > 31 { - y.Set(zero) - } else { - sh := (31 - indx) * 8 - y.Rsh(y, uint(sh)) - y.And(y, opByteMask) - } + y = y.Byte(&x) } func opNot(c *state) { a := c.top() - a.Not(a) - toU256(a) } func opIsZero(c *state) { a := c.top() - if a.Sign() == 0 { - a.Set(one) + if a.IsZero() { + a.SetOne() } else { - a.Set(zero) + a.SetUint64(0) } } @@ -262,10 +210,10 @@ func opEq(c *state) { a := c.pop() b := c.top() - if a.Cmp(b) == 0 { - b.Set(one) + if a.Eq(b) { + b.SetOne() } else { - b.Set(zero) + b.SetUint64(0) } } @@ -273,10 +221,10 @@ func opLt(c *state) { a := c.pop() b := c.top() - if a.Cmp(b) < 0 { - b.Set(one) + if a.Lt(b) { + b.SetOne() } else { - b.Set(zero) + b.SetUint64(0) } } @@ -284,32 +232,32 @@ func opGt(c *state) { a := c.pop() b := c.top() - if a.Cmp(b) > 0 { - b.Set(one) + if a.Gt(b) { + b.SetOne() } else { - b.Set(zero) + b.SetUint64(0) } } func opSlt(c *state) { - a := to256(c.pop()) - b := to256(c.top()) + a := c.pop() + b := c.top() - if a.Cmp(b) < 0 { - b.Set(one) + if a.Slt(b) { + b.SetOne() } else { - b.Set(zero) + b.SetUint64(0) } } func opSgt(c *state) { - a := to256(c.pop()) - b := to256(c.top()) + a := c.pop() + b := c.top() - if a.Cmp(b) > 0 { - b.Set(one) + if a.Sgt(b) { + b.SetOne() } else { - b.Set(zero) + b.SetUint64(0) } } @@ -317,33 +265,7 @@ func opSignExtension(c *state) { ext := c.pop() x := c.top() - if ext.Cmp(wordSize) > 0 { - return - } - - if x == nil { - return - } - - bit := uint(ext.Uint64()*8 + 7) - - mask := acquireBig().Set(one) - mask.Lsh(mask, bit) - mask.Sub(mask, one) - - if x.Bit(int(bit)) > 0 { - mask.Not(mask) - x.Or(x, mask) - } else { - x.And(x, mask) - } - - toU256(x) - releaseBig(mask) -} - -func equalOrOverflowsUint256(b *big.Int) bool { - return b.BitLen() > 8 + x.ExtendSign(x, &ext) } func opShl(c *state) { @@ -356,11 +278,10 @@ func opShl(c *state) { shift := c.pop() value := c.top() - if equalOrOverflowsUint256(shift) { - value.Set(zero) - } else { + if shift.LtUint64(256) { value.Lsh(value, uint(shift.Uint64())) - toU256(value) + } else { + value.Clear() } } @@ -374,11 +295,10 @@ func opShr(c *state) { shift := c.pop() value := c.top() - if equalOrOverflowsUint256(shift) { - value.Set(zero) - } else { + if shift.LtUint64(256) { value.Rsh(value, uint(shift.Uint64())) - toU256(value) + } else { + value.Clear() } } @@ -390,88 +310,54 @@ func opSar(c *state) { } shift := c.pop() - value := to256(c.top()) + value := c.top() - if equalOrOverflowsUint256(shift) { + // This seams like unneeded since uint256 is maximum value + if equalOrOverflowsUint256(shift.ToBig()) { if value.Sign() >= 0 { - value.Set(zero) + value.SetUint64(0) } else { - value.Set(tt256m1) + value.SetAllOne() } } else { - value.Rsh(value, uint(shift.Uint64())) - toU256(value) + value.SRsh(value, uint(shift.Uint64())) } } // memory operations - -var bufPool = sync.Pool{ - New: func() interface{} { - // Store pointer to avoid heap allocation in caller - // Please check SA6002 in StaticCheck for details - buf := make([]byte, 128) - - return &buf - }, -} - func opMLoad(c *state) { - offset := c.pop() + v := c.top() + //offset := v.ToBig() var ok bool - c.tmp, ok = c.get2(c.tmp[:0], offset, wordSize) + c.tmp, ok = c.get2(c.tmp[:0], *v, *wordSize256) + // ### Error handling? if !ok { return } - c.push1().SetBytes(c.tmp) + v.SetBytes(c.tmp) } -var ( - _W = bits.UintSize - _S = _W / 8 -) - func opMStore(c *state) { offset := c.pop() val := c.pop() - if !c.allocateMemory(offset, wordSize) { + if !c.allocateMemory(offset, *wordSize256) { return } o := offset.Uint64() - buf := c.memory[o : o+32] - - i := 32 - - // convert big.int to bytes - // https://golang.org/src/math/big/nat.go#L1284 - for _, d := range val.Bits() { - for j := 0; j < _S; j++ { - i-- - buf[i] = byte(d) - - d >>= 8 - } - } - - // fill the rest of the slot with zeros - for i > 0 { - i-- - - buf[i] = 0 - } + val.WriteToSlice(c.memory[o : o+32]) } func opMStore8(c *state) { offset := c.pop() val := c.pop() - if !c.allocateMemory(offset, one) { + if !c.allocateMemory(offset, *uint256.NewInt(1)) { return } @@ -486,10 +372,10 @@ func opSload(c *state) { var gas uint64 if c.config.Berlin { - if _, slotPresent := c.host.ContainsAccessListSlot(c.msg.Address, bigToHash(loc)); !slotPresent { + if _, slotPresent := c.host.ContainsAccessListSlot(c.msg.Address, bigToHash(loc.ToBig())); !slotPresent { gas = ColdStorageReadCostEIP2929 - c.host.AddSlotToAccessList(c.msg.Address, bigToHash(loc)) + c.host.AddSlotToAccessList(c.msg.Address, bigToHash(loc.ToBig())) } else { gas = WarmStorageReadCostEIP2929 } @@ -506,7 +392,7 @@ func opSload(c *state) { return } - val := c.host.GetStorage(c.msg.Address, bigToHash(loc)) + val := c.host.GetStorage(c.msg.Address, bigToHash(loc.ToBig())) loc.SetBytes(val.Bytes()) } @@ -603,8 +489,9 @@ func opSha3(c *state) { c.tmp = keccak.Keccak256(c.tmp[:0], c.tmp) - v := c.push1() + v := uint256.NewInt(0) v.SetBytes(c.tmp) + c.push(*v) } func opPop(c *state) { @@ -614,7 +501,9 @@ func opPop(c *state) { // context operations func opAddress(c *state) { - c.push1().SetBytes(c.msg.Address.Bytes()) + v := uint256.NewInt(0) + v.SetBytes(c.msg.Address.Bytes()) + c.push(*v) } func opBalance(c *state) { @@ -636,7 +525,10 @@ func opBalance(c *state) { return } - c.push1().Set(c.host.GetBalance(addr)) + balance := c.host.GetBalance(addr) + uintBalance, _ := uint256.FromBig(balance) + + c.push(*uintBalance) } func opSelfBalance(c *state) { @@ -646,7 +538,10 @@ func opSelfBalance(c *state) { return } - c.push1().Set(c.host.GetBalance(c.msg.Address)) + balance := c.host.GetBalance(c.msg.Address) + uintBalance, _ := uint256.FromBig(balance) + + c.push(*uintBalance) } func opChainID(c *state) { @@ -656,32 +551,32 @@ func opChainID(c *state) { return } - c.push1().SetUint64(uint64(c.host.GetTxContext().ChainID)) + x := uint256.NewInt(uint64(c.host.GetTxContext().ChainID)) + + c.push(*x) } func opOrigin(c *state) { - c.push1().SetBytes(c.host.GetTxContext().Origin.Bytes()) + x := uint256.NewInt(0) + x.SetBytes(c.host.GetTxContext().Origin.Bytes()) + + c.push(*x) } func opCaller(c *state) { - c.push1().SetBytes(c.msg.Caller.Bytes()) + x := uint256.NewInt(0) + x.SetBytes(c.msg.Caller.Bytes()) + + c.push(*x) } func opCallValue(c *state) { - v := c.push1() if value := c.msg.Value; value != nil { - v.Set(value) + uintValue, _ := uint256.FromBig(value) + c.push(*uintValue) } else { - v.Set(zero) - } -} - -func min(i, j uint64) uint64 { - if i < j { - return i + c.push(*uint256.NewInt(0)) } - - return j } func opCallDataLoad(c *state) { @@ -689,17 +584,19 @@ func opCallDataLoad(c *state) { bufPtr := bufPool.Get().(*[]byte) buf := *bufPtr - c.setBytes(buf[:32], c.msg.Input, 32, offset) + c.setBytes(buf[:32], c.msg.Input, 32, offset.ToBig()) offset.SetBytes(buf[:32]) bufPool.Put(bufPtr) } func opCallDataSize(c *state) { - c.push1().SetUint64(uint64(len(c.msg.Input))) + x := uint256.NewInt(uint64(len(c.msg.Input))) + c.push(*x) } func opCodeSize(c *state) { - c.push1().SetUint64(uint64(len(c.code))) + x := uint256.NewInt(uint64(len(c.code))) + c.push(*x) } func opExtCodeSize(c *state) { @@ -718,18 +615,22 @@ func opExtCodeSize(c *state) { return } - c.push1().SetUint64(uint64(c.host.GetCodeSize(addr))) + x := uint256.NewInt(uint64(c.host.GetCodeSize(addr))) + c.push(*x) } func opGasPrice(c *state) { - c.push1().SetBytes(c.host.GetTxContext().GasPrice.Bytes()) + x := uint256.NewInt(0) + x.SetBytes(c.host.GetTxContext().GasPrice.Bytes()) + c.push(*x) } func opReturnDataSize(c *state) { if !c.config.Byzantium { c.exit(errOpCodeNotFound) } else { - c.push1().SetUint64(uint64(len(c.returnData))) + x := uint256.NewInt(uint64(len(c.returnData))) + c.push(*x) } } @@ -755,24 +656,24 @@ func opExtCodeHash(c *state) { return } - v := c.push1() - if c.host.Empty(address) { - v.Set(zero) - } else { + v := uint256.NewInt(0) + if !c.host.Empty(address) { v.SetBytes(c.host.GetCodeHash(address).Bytes()) } + + c.push(*v) } func opPC(c *state) { - c.push1().SetUint64(uint64(c.ip)) + c.push(*uint256.NewInt(uint64(c.ip))) } func opMSize(c *state) { - c.push1().SetUint64(uint64(len(c.memory))) + c.push(*uint256.NewInt(uint64(len(c.memory)))) } func opGas(c *state) { - c.push1().SetUint64(c.gas) + c.push(*uint256.NewInt(c.gas)) } func (c *state) setBytes(dst, input []byte, size uint64, dataOffset *big.Int) { @@ -833,7 +734,7 @@ func opExtCodeCopy(c *state) { code := c.host.GetCode(address) if size != 0 { - c.setBytes(c.memory[memOffset.Uint64():], code, size, codeOffset) + c.setBytes(c.memory[memOffset.Uint64():], code, size, codeOffset.ToBig()) } } @@ -852,7 +753,7 @@ func opCallDataCopy(c *state) { } if size != 0 { - c.setBytes(c.memory[memOffset.Uint64():], c.msg.Input, size, dataOffset) + c.setBytes(c.memory[memOffset.Uint64():], c.msg.Input, size, dataOffset.ToBig()) } } @@ -873,7 +774,7 @@ func opReturnDataCopy(c *state) { // 1. the dataOffset is uint64 (overflow check) // 2. the sum of dataOffset and length overflows uint64 // 3. the length of return data has enough space to receive offset + length bytes - end := new(big.Int).Add(dataOffset, length) + end := new(big.Int).Add(dataOffset.ToBig(), length.ToBig()) endAddress := end.Uint64() if !dataOffset.IsUint64() || @@ -923,49 +824,56 @@ func opCodeCopy(c *state) { } if size != 0 { - c.setBytes(c.memory[memOffset.Uint64():], c.code, size, dataOffset) + c.setBytes(c.memory[memOffset.Uint64():], c.code, size, dataOffset.ToBig()) } } -// block information +// block information< func opBlockHash(c *state) { num := c.top() - if !num.IsInt64() { - num.Set(zero) + num64, overflow := num.Uint64WithOverflow() + + if overflow { + num.SetUint64(0) return } - n := num.Int64() + n := int64(num64) lastBlock := c.host.GetTxContext().Number if lastBlock-257 < n && n < lastBlock { num.SetBytes(c.host.GetBlockHash(n).Bytes()) } else { - num.Set(zero) + num.SetUint64(0) } } func opCoinbase(c *state) { - c.push1().SetBytes(c.host.GetTxContext().Coinbase.Bytes()) + v := new(uint256.Int).SetBytes20(c.host.GetTxContext().Coinbase.Bytes()) + c.push(*v) } func opTimestamp(c *state) { - c.push1().SetInt64(c.host.GetTxContext().Timestamp) + v := new(uint256.Int).SetUint64(uint64(c.host.GetTxContext().Timestamp)) + c.push(*v) } func opNumber(c *state) { - c.push1().SetInt64(c.host.GetTxContext().Number) + v := new(uint256.Int).SetUint64((uint64)(c.host.GetTxContext().Number)) + c.push(*v) } func opDifficulty(c *state) { - c.push1().SetBytes(c.host.GetTxContext().Difficulty.Bytes()) + v := new(uint256.Int).SetBytes(c.host.GetTxContext().Difficulty.Bytes()) + c.push(*v) } func opGasLimit(c *state) { - c.push1().SetInt64(c.host.GetTxContext().GasLimit) + v := new(uint256.Int).SetUint64((uint64)(c.host.GetTxContext().GasLimit)) + c.push(*v) } func opBaseFee(c *state) { @@ -975,7 +883,7 @@ func opBaseFee(c *state) { return } - c.push(c.host.GetTxContext().BaseFee) + c.push(*uint256.MustFromBig(c.host.GetTxContext().BaseFee)) } func opSelfDestruct(c *state) { @@ -1020,7 +928,7 @@ func opSelfDestruct(c *state) { } func opJump(c *state) { - if dest := c.pop(); c.validJumpdest(dest) { + if dest := c.pop(); c.validJumpdest(dest.ToBig()) { c.ip = int(dest.Uint64() - 1) } else { c.exit(errInvalidJump) @@ -1032,7 +940,7 @@ func opJumpi(c *state) { cond := c.pop() if cond.Sign() != 0 { - if c.validJumpdest(dest) { + if c.validJumpdest(dest.ToBig()) { c.ip = int(dest.Uint64() - 1) } else { c.exit(errInvalidJump) @@ -1050,7 +958,7 @@ func opPush0(c *state) { return } - c.push(zero) + c.push(*uint256.NewInt(0)) } func opPush(n int) instruction { @@ -1058,11 +966,14 @@ func opPush(n int) instruction { ins := c.code ip := c.ip - v := c.push1() if ip+1+n > len(ins) { - v.SetBytes(append(ins[ip+1:], make([]byte, n)...)) + d := uint256.NewInt(0) + d.SetBytes(append(ins[ip+1:], make([]byte, n)...)) + c.push(*d) } else { - v.SetBytes(ins[ip+1 : ip+1+n]) + d := uint256.NewInt(0) + d.SetBytes(ins[ip+1 : ip+1+n]) + c.push(*d) } c.ip += n @@ -1072,10 +983,10 @@ func opPush(n int) instruction { func opDup(n int) instruction { return func(c *state) { if !c.stackAtLeast(n) { - c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: n}) + c.exit(&runtime.StackUnderflowError{StackLen: c.stack.sp, Required: n}) } else { val := c.peekAt(n) - c.push1().Set(val) + c.push(val) } } } @@ -1083,7 +994,7 @@ func opDup(n int) instruction { func opSwap(n int) instruction { return func(c *state) { if !c.stackAtLeast(n + 1) { - c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: n + 1}) + c.exit(&runtime.StackUnderflowError{StackLen: c.stack.sp, Required: n + 1}) } else { c.swap(n) } @@ -1101,7 +1012,7 @@ func opLog(size int) instruction { } if !c.stackAtLeast(2 + size) { - c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: 2 + size}) + c.exit(&runtime.StackUnderflowError{StackLen: c.stack.sp, Required: 2 + size}) return } @@ -1111,7 +1022,8 @@ func opLog(size int) instruction { topics := make([]types.Hash, size) for i := 0; i < size; i++ { - topics[i] = bigToHash(c.pop()) + v := c.pop() + topics[i] = bigToHash(v.ToBig()) } var ok bool @@ -1158,7 +1070,7 @@ func opCreate(op OpCode) instruction { contract, err := c.buildCreateContract(op) if err != nil { - c.push1().Set(zero) + c.push(*uint256.NewInt(0)) if contract != nil { c.gas += contract.Gas @@ -1176,17 +1088,18 @@ func opCreate(op OpCode) instruction { // Correct call result := c.host.Callx(contract, c.host) - v := c.push1() + v := uint256.NewInt(0) if op == CREATE && c.config.Homestead && errors.Is(result.Err, runtime.ErrCodeStoreOutOfGas) { - v.Set(zero) + v.SetUint64(0) } else if op == CREATE && result.Failed() && !errors.Is(result.Err, runtime.ErrCodeStoreOutOfGas) { - v.Set(zero) + v.SetUint64(0) } else if op == CREATE2 && result.Failed() { - v.Set(zero) + v.SetUint64(0) } else { v.SetBytes(contract.Address.Bytes()) } + c.push(*v) c.gas += result.GasLeft if result.Reverted() { @@ -1200,7 +1113,7 @@ func opCall(op OpCode) instruction { c.resetReturnData() if op == CALL && c.inStaticCall() { - if val := c.peekAt(3); val != nil && val.BitLen() > 0 { + if val := c.peekAt(3); val.BitLen() > 0 { c.exit(errWriteProtection) return @@ -1240,7 +1153,7 @@ func opCall(op OpCode) instruction { contract, offset, size, err := c.buildCallContract(op) if err != nil { - c.push1().Set(zero) + c.push(*uint256.NewInt(0)) if contract != nil { c.gas += contract.Gas @@ -1257,11 +1170,10 @@ func opCall(op OpCode) instruction { result := c.host.Callx(contract, c.host) - v := c.push1() if result.Succeeded() { - v.Set(one) + c.push(*uint256.NewInt(1)) } else { - v.Set(zero) + c.push(*uint256.NewInt(0)) } if result.Succeeded() || result.Reverted() { @@ -1282,7 +1194,8 @@ func (c *state) buildCallContract(op OpCode) (*runtime.Contract, uint64, uint64, var value *big.Int if op == CALL || op == CALLCODE { - value = c.pop() + v := c.pop() + value = v.ToBig() } // input range @@ -1410,11 +1323,12 @@ func (c *state) buildCreateContract(op OpCode) (*runtime.Contract, error) { var salt *big.Int if op == CREATE2 { - salt = c.pop() + v := c.pop() + salt = v.ToBig() } // check if the value can be transferred - hasTransfer := value != nil && value.Sign() != 0 + hasTransfer := value.Sign() != 0 // Calculate and consume gas cost @@ -1437,7 +1351,7 @@ func (c *state) buildCreateContract(op OpCode) (*runtime.Contract, error) { } if hasTransfer { - if c.host.GetBalance(c.msg.Address).Cmp(value) < 0 { + if c.host.GetBalance(c.msg.Address).Cmp(value.ToBig()) < 0 { return nil, types.ErrInsufficientFunds } } @@ -1467,7 +1381,7 @@ func (c *state) buildCreateContract(op OpCode) (*runtime.Contract, error) { c.msg.Origin, c.msg.Address, address, - value, + value.ToBig(), gas, input, ) diff --git a/state/runtime/evm/instructions_benchmark_test.go b/state/runtime/evm/instructions_benchmark_test.go new file mode 100644 index 0000000000..115a3bff80 --- /dev/null +++ b/state/runtime/evm/instructions_benchmark_test.go @@ -0,0 +1,233 @@ +package evm + +import ( + "testing" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/holiman/uint256" +) + +type ( + instructionOperation func(c *state) +) + +func BenchmarkStack(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + op1 := uint256.NewInt(1) + op2 := uint256.NewInt(2) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + s.push(*op1) + s.push(*op2) + s.pop() + s.pop() + } + + b.StopTimer() +} + +func operationBenchmark(b *testing.B, s *state, op instructionOperation, op1 uint256.Int, op2 uint256.Int) { + b.Helper() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + s.push(op1) + s.push(op2) + op(s) + s.pop() + } + + b.StopTimer() +} + +func BenchmarkInstruction_opAdd(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opAdd, *op1, *op2) +} + +func BenchmarkInstruction_opMul(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opMul, *op1, *op2) +} + +func BenchmarkInstruction_opSub(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opSub, *op1, *op2) +} + +func BenchmarkInstruction_opDiv(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opDiv, *op1, *op2) +} + +func BenchmarkInstruction_opSDiv(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opSDiv, *op1, *op2) +} + +func BenchmarkInstruction_opMod(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opMod, *op1, *op2) +} + +func BenchmarkInstruction_opSMod(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opSMod, *op1, *op2) +} + +func BenchmarkInstruction_opExp(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opExp, *op1, *op2) +} + +func BenchmarkInstruction_opAnd(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opAnd, *op1, *op2) +} + +func BenchmarkInstruction_opOr(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opOr, *op1, *op2) +} + +func BenchmarkInstruction_opXor(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opXor, *op1, *op2) +} + +func BenchmarkInstruction_opByte(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opByte, *op1, *op2) +} + +func BenchmarkInstruction_opEq(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opEq, *op1, *op2) +} + +func BenchmarkInstruction_opLt(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opLt, *op1, *op2) +} + +func BenchmarkInstruction_opGt(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opGt, *op1, *op2) +} + +func BenchmarkInstruction_opSlt(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opSlt, *op1, *op2) +} + +func BenchmarkInstruction_opSgt(b *testing.B) { + s, closeFn := getState(&chain.ForksInTime{}) + defer closeFn() + + s.gas = 9223372036854775807 + op1 := uint256.NewInt(9223372036854775807) + op2 := uint256.NewInt(9223372036854775807) + + operationBenchmark(b, s, opSgt, *op1, *op2) +} diff --git a/state/runtime/evm/instructions_test.go b/state/runtime/evm/instructions_test.go index 143921b989..ea85679369 100644 --- a/state/runtime/evm/instructions_test.go +++ b/state/runtime/evm/instructions_test.go @@ -10,6 +10,7 @@ import ( "github.com/0xPolygon/polygon-edge/crypto" "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" + "github.com/holiman/uint256" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -33,15 +34,17 @@ func testLogicalOperation(t *testing.T, f instruction, test OperandsLogical, s * t.Helper() for _, operand := range test.operands { - s.push(operand) + op, _ := uint256.FromBig(operand) + s.push(*op) } f(s) + r := s.pop() if test.expectedResult { - assert.Equal(t, one.Uint64(), s.pop().Uint64()) + assert.Equal(t, one.Uint64(), r.Uint64()) } else { - assert.Equal(t, zero.Uint64(), s.pop().Uint64()) + assert.Equal(t, zero.Uint64(), r.Uint64()) } } @@ -54,12 +57,14 @@ func testArithmeticOperation(t *testing.T, f instruction, test OperandsArithmeti t.Helper() for _, operand := range test.operands { - s.push(operand) + op, _ := uint256.FromBig(operand) + s.push(*op) } f(s) - assert.Equal(t, test.expectedResult.Uint64(), s.pop().Uint64()) + r := s.pop() + assert.Equal(t, test.expectedResult.Uint64(), r.Uint64()) } func TestAdd(t *testing.T) { @@ -357,7 +362,8 @@ func TestPush0(t *testing.T) { defer closeFn() opPush0(s) - require.Equal(t, zero.Uint64(), s.pop().Uint64()) + v := s.pop() + require.Equal(t, zero.Uint64(), v.Uint64()) }) t.Run("single push0 (EIP-3855 disabled)", func(t *testing.T) { @@ -380,7 +386,8 @@ func TestPush0(t *testing.T) { } for i := 0; i < stackSize; i++ { - require.Equal(t, zero.Uint64(), s.pop().Uint64()) + v := s.pop() + require.Equal(t, zero.Uint64(), v.Uint64()) } }) } @@ -531,40 +538,42 @@ func TestIsZero(t *testing.T) { } func TestMStore(t *testing.T) { - offset := big.NewInt(62) + offset := uint256.NewInt(62) s, closeFn := getState(&chain.ForksInTime{}) defer closeFn() - s.push(one) // value - s.push(offset) // offset + s.push(*uint256.NewInt(1)) // value + s.push(*offset) // offset opMStore(s) - s.push(offset) + s.push(*offset) opMLoad(s) - assert.Equal(t, one, s.pop()) + v := s.pop() + assert.Equal(t, one, v.ToBig()) } func TestMStore8(t *testing.T) { - offsetStore := big.NewInt(62) - offsetLoad := big.NewInt(31) + offsetStore := uint256.NewInt(62) + offsetLoad := uint256.NewInt(31) s, closeFn := getState(&chain.ForksInTime{}) defer closeFn() - s.push(one) //value - s.push(offsetStore) //offset + s.push(*uint256.NewInt(1)) //value + s.push(*offsetStore) //offset opMStore8(s) - s.push(offsetLoad) + s.push(*offsetLoad) opMLoad(s) - assert.Equal(t, one, s.pop()) + v := s.pop() + assert.Equal(t, one, v.ToBig()) } func TestSload(t *testing.T) { @@ -576,11 +585,12 @@ func TestSload(t *testing.T) { mockHost.On("GetStorage", mock.Anything, mock.Anything).Return(bigToHash(one)).Once() s.host = mockHost - s.push(one) + s.push(*uint256.NewInt(1)) opSload(s) assert.Equal(t, uint64(200), s.gas) - assert.Equal(t, bigToHash(one), bigToHash(s.pop())) + v := s.pop() + assert.Equal(t, bigToHash(one), bigToHash(v.ToBig())) }) t.Run("EIP150", func(t *testing.T) { @@ -591,11 +601,12 @@ func TestSload(t *testing.T) { mockHost.On("GetStorage", mock.Anything, mock.Anything).Return(bigToHash(one)).Once() s.host = mockHost - s.push(one) + s.push(*uint256.NewInt(1)) opSload(s) assert.Equal(t, uint64(800), s.gas) - assert.Equal(t, bigToHash(one), bigToHash(s.pop())) + v := s.pop() + assert.Equal(t, bigToHash(one), bigToHash(v.ToBig())) }) t.Run("NoForks", func(t *testing.T) { @@ -606,11 +617,12 @@ func TestSload(t *testing.T) { mockHost.On("GetStorage", mock.Anything, mock.Anything).Return(bigToHash(one)).Once() s.host = mockHost - s.push(one) + s.push(*uint256.NewInt(1)) opSload(s) assert.Equal(t, uint64(950), s.gas) - assert.Equal(t, bigToHash(one), bigToHash(s.pop())) + v := s.pop() + assert.Equal(t, bigToHash(one), bigToHash(v.ToBig())) }) } @@ -621,7 +633,7 @@ func TestSStore(t *testing.T) { }) defer closeFn() - s.push(one) + s.push(*uint256.NewInt(1)) opSStore(s) assert.True(t, s.stop) @@ -641,8 +653,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageUnchanged).Once() s.host = mockHost - s.push(one) - s.push(zero) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(0)) opSStore(s) assert.Equal(t, uint64(9200), s.gas) @@ -661,8 +673,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageModified).Once() s.host = mockHost - s.push(one) - s.push(zero) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(0)) opSStore(s) assert.Equal(t, uint64(5000), s.gas) @@ -678,8 +690,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageAdded).Once() s.host = mockHost - s.push(one) - s.push(zero) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(0)) opSStore(s) assert.Equal(t, uint64(5000), s.gas) @@ -698,8 +710,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageDeleted).Once() s.host = mockHost - s.push(one) - s.push(zero) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(0)) opSStore(s) assert.Equal(t, uint64(5000), s.gas) @@ -726,7 +738,8 @@ func TestBalance(t *testing.T) { opBalance(s) - assert.Equal(t, balance, s.pop()) + v := s.pop() + assert.Equal(t, balance, v.ToBig()) assert.Equal(t, gasLeft, s.gas) }) @@ -740,7 +753,8 @@ func TestBalance(t *testing.T) { opBalance(s) - assert.Equal(t, big.NewInt(100), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(100), v.ToBig()) assert.Equal(t, gasLeft, s.gas) }) @@ -754,7 +768,8 @@ func TestBalance(t *testing.T) { opBalance(s) - assert.Equal(t, balance, s.pop()) + v := s.pop() + assert.Equal(t, balance, v.ToBig()) assert.Equal(t, gasLeft, s.gas) }) } @@ -772,7 +787,8 @@ func TestSelfBalance(t *testing.T) { opSelfBalance(s) - assert.Equal(t, big.NewInt(100), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(100), v.ToBig()) }) t.Run("NoForkErrorExpected", func(t *testing.T) { @@ -803,7 +819,8 @@ func TestChainID(t *testing.T) { opChainID(s) - assert.Equal(t, big.NewInt(chainID), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(chainID), v.ToBig()) }) t.Run("NoForksErrorExpected", func(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) @@ -859,7 +876,8 @@ func TestCallValue(t *testing.T) { s.msg.Value = value opCallValue(s) - assert.Equal(t, value.Uint64(), s.pop().Uint64()) + v := s.pop() + assert.Equal(t, value.Uint64(), v.Uint64()) }) t.Run("Msg Value nil", func(t *testing.T) { @@ -867,7 +885,8 @@ func TestCallValue(t *testing.T) { defer cancelFn() opCallValue(s) - assert.Equal(t, zero.Uint64(), s.pop().Uint64()) + v := s.pop() + assert.Equal(t, zero.Uint64(), v.Uint64()) }) } @@ -875,12 +894,13 @@ func TestCallDataLoad(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(one) + s.push(*uint256.NewInt(1)) s.msg = &runtime.Contract{Input: big.NewInt(7).Bytes()} opCallDataLoad(s) - assert.Equal(t, zero.Uint64(), s.pop().Uint64()) + v := s.pop() + assert.Equal(t, zero.Uint64(), v.Uint64()) } func TestCallDataSize(t *testing.T) { @@ -890,7 +910,8 @@ func TestCallDataSize(t *testing.T) { s.msg.Input = make([]byte, 10) opCallDataSize(s) - assert.Equal(t, big.NewInt(10), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(10), v.ToBig()) } func TestCodeSize(t *testing.T) { @@ -900,7 +921,8 @@ func TestCodeSize(t *testing.T) { s.code = make([]byte, 10) opCodeSize(s) - assert.Equal(t, big.NewInt(10), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(10), v.ToBig()) } func TestExtCodeSize(t *testing.T) { @@ -911,7 +933,7 @@ func TestExtCodeSize(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{EIP150: true}) defer cancelFn() - s.push(one) + s.push(*uint256.NewInt(1)) mockHost := &mockHost{} mockHost.On("GetCodeSize", types.StringToAddress("0x1")).Return(codeSize).Once() @@ -920,7 +942,8 @@ func TestExtCodeSize(t *testing.T) { opExtCodeSize(s) assert.Equal(t, gasLeft, s.gas) - assert.Equal(t, big.NewInt(int64(codeSize)), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(int64(codeSize)), v.ToBig()) }) t.Run("NoForks", func(t *testing.T) { gasLeft := uint64(980) @@ -928,7 +951,7 @@ func TestExtCodeSize(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(one) + s.push(*uint256.NewInt(1)) mockHost := &mockHost{} mockHost.On("GetCodeSize", types.StringToAddress("0x1")).Return(codeSize).Once() @@ -937,7 +960,8 @@ func TestExtCodeSize(t *testing.T) { opExtCodeSize(s) assert.Equal(t, gasLeft, s.gas) - assert.Equal(t, big.NewInt(int64(codeSize)), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(int64(codeSize)), v.ToBig()) }) } @@ -967,7 +991,8 @@ func TestReturnDataSize(t *testing.T) { opReturnDataSize(s) - assert.Equal(t, big.NewInt(dataSize), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(dataSize), v.ToBig()) }) t.Run("NoForks", func(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) @@ -992,7 +1017,7 @@ func TestExtCodeHash(t *testing.T) { }) defer cancelFn() - s.push(one) + s.push(*uint256.NewInt(1)) mockHost := &mockHost{} mockHost.On("Empty", types.StringToAddress("0x1")).Return(false).Once() @@ -1002,7 +1027,8 @@ func TestExtCodeHash(t *testing.T) { opExtCodeHash(s) assert.Equal(t, s.gas, gasLeft) - assert.Equal(t, one.Uint64(), s.pop().Uint64()) + v := s.pop() + assert.Equal(t, one.Uint64(), v.Uint64()) }) t.Run("NonIstanbul", func(t *testing.T) { @@ -1013,7 +1039,7 @@ func TestExtCodeHash(t *testing.T) { }) defer cancelFn() - s.push(one) + s.push(*uint256.NewInt(1)) mockHost := &mockHost{} mockHost.On("Empty", mock.Anything).Return(true).Once() @@ -1021,14 +1047,15 @@ func TestExtCodeHash(t *testing.T) { opExtCodeHash(s) assert.Equal(t, gasLeft, s.gas) - assert.Equal(t, zero.Uint64(), s.pop().Uint64()) + v := s.pop() + assert.Equal(t, zero.Uint64(), v.Uint64()) }) t.Run("NoForks", func(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(one) + s.push(*uint256.NewInt(1)) mockHost := &mockHost{} mockHost.On("Empty", mock.Anything).Return(true).Once() @@ -1051,7 +1078,8 @@ func TestPCMSizeGas(t *testing.T) { s.ip = 1 opPC(s) - assert.Equal(t, one, s.pop()) + v := s.pop() + assert.Equal(t, one, v.ToBig()) }) t.Run("MSize", func(t *testing.T) { @@ -1059,13 +1087,15 @@ func TestPCMSizeGas(t *testing.T) { opMSize(s) - assert.Equal(t, new(big.Int).SetUint64(memorySize), s.pop()) + v := s.pop() + assert.Equal(t, new(big.Int).SetUint64(memorySize), v.ToBig()) }) t.Run("Gas", func(t *testing.T) { opGas(s) - assert.Equal(t, new(big.Int).SetUint64(gasLeft), s.pop()) + v := s.pop() + assert.Equal(t, new(big.Int).SetUint64(gasLeft), v.ToBig()) }) } @@ -1080,10 +1110,10 @@ func TestExtCodeCopy(t *testing.T) { mockHost.On("GetCode", mock.Anything).Return("0x1").Once() s.host = mockHost - s.push(one) - s.push(zero) - s.push(big.NewInt(31)) - s.push(big.NewInt(32)) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(0)) + s.push(*uint256.NewInt(31)) + s.push(*uint256.NewInt(32)) opExtCodeCopy(s) @@ -1100,10 +1130,10 @@ func TestExtCodeCopy(t *testing.T) { mockHost.On("GetCode", mock.Anything).Return("0x1").Once() s.host = mockHost - s.push(one) - s.push(zero) - s.push(big.NewInt(31)) - s.push(big.NewInt(32)) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(0)) + s.push(*uint256.NewInt(31)) + s.push(*uint256.NewInt(32)) opExtCodeCopy(s) @@ -1120,9 +1150,9 @@ func TestCallDataCopy(t *testing.T) { s.msg.Input = one.Bytes() - s.push(big.NewInt(1)) - s.push(zero) - s.push(big.NewInt(31)) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(0)) + s.push(*uint256.NewInt(31)) opCallDataCopy(s) @@ -1136,9 +1166,9 @@ func TestCodeCopyLenZero(t *testing.T) { var expectedGas = s.gas - s.push(big.NewInt(0)) //length - s.push(big.NewInt(0)) //dataOffset - s.push(big.NewInt(0)) //memOffset + s.push(*uint256.NewInt(0)) //length + s.push(*uint256.NewInt(0)) //dataOffset + s.push(*uint256.NewInt(0)) //memOffset opCodeCopy(s) @@ -1151,9 +1181,9 @@ func TestCodeCopy(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(big.NewInt(1)) //length - s.push(zero) //dataOffset - s.push(big.NewInt(31)) //memOffset + s.push(*uint256.NewInt(1)) //length + s.push(*uint256.NewInt(0)) //dataOffset + s.push(*uint256.NewInt(31)) //memOffset s.code = one.Bytes() @@ -1165,7 +1195,7 @@ func TestBlockHash(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(three) + s.push(*uint256.NewInt(3)) mockHost := &mockHost{} mockHost.On("GetTxContext").Return(runtime.TxContext{Number: 5}).Once() @@ -1174,7 +1204,8 @@ func TestBlockHash(t *testing.T) { opBlockHash(s) - assert.Equal(t, bigToHash(three), bigToHash(s.pop())) + v := s.pop() + assert.Equal(t, bigToHash(three), bigToHash(v.ToBig())) } func TestCoinBase(t *testing.T) { @@ -1187,7 +1218,10 @@ func TestCoinBase(t *testing.T) { opCoinbase(s) - assert.Equal(t, types.StringToAddress("0x1").Bytes(), s.pop().FillBytes(make([]byte, 20))) + v := s.pop() + b := v.ToBig().FillBytes(make([]byte, 20)) + a := types.StringToAddress("0x1").Bytes() + assert.Equal(t, a, b) } func TestTimeStamp(t *testing.T) { @@ -1200,7 +1234,8 @@ func TestTimeStamp(t *testing.T) { opTimestamp(s) - assert.Equal(t, big.NewInt(335), s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(335), v.ToBig()) } func TestNumber(t *testing.T) { @@ -1213,7 +1248,8 @@ func TestNumber(t *testing.T) { opNumber(s) - assert.Equal(t, five, s.pop()) + v := s.pop() + assert.Equal(t, five, v.ToBig()) } func TestDifficulty(t *testing.T) { @@ -1226,7 +1262,8 @@ func TestDifficulty(t *testing.T) { opDifficulty(s) - assert.Equal(t, bigToHash(five), bigToHash(s.pop())) + v := s.pop() + assert.Equal(t, bigToHash(five), bigToHash(v.ToBig())) } func TestGasLimit(t *testing.T) { @@ -1254,7 +1291,8 @@ func TestGasLimit(t *testing.T) { opBaseFee(s) - assert.Equal(t, new(big.Int).SetUint64(baseFee), s.pop()) + v := s.pop() + assert.Equal(t, new(big.Int).SetUint64(baseFee), v.ToBig()) }) } @@ -1269,7 +1307,7 @@ func TestSelfDestruct(t *testing.T) { s.msg.Address = types.StringToAddress("0x2") s.gas = 100000 - s.push(one) + s.push(*uint256.NewInt(1)) mockHost := &mockHost{} mockHost.On("Empty", addr).Return(true).Once() @@ -1289,7 +1327,7 @@ func TestJump(t *testing.T) { s.code = make([]byte, 10) s.bitmap = bitmap{big.NewInt(255).Bytes()} - s.push(five) + s.push(*uint256.NewInt(5)) opJump(s) @@ -1302,8 +1340,8 @@ func TestJumpI(t *testing.T) { s.code = make([]byte, 10) s.bitmap = bitmap{big.NewInt(255).Bytes()} - s.push(one) - s.push(five) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(5)) opJumpi(s) @@ -1314,33 +1352,30 @@ func TestDup(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.sp = 6 - for i := 0; i < 10; i++ { - s.stack = append(s.stack, big.NewInt(int64(i))) + s.push(*uint256.NewInt(uint64(i))) } instr := opDup(4) instr(s) - assert.Equal(t, two, s.pop()) + v := s.pop() + assert.Equal(t, big.NewInt(6), v.ToBig()) } func TestSwap(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.sp = 6 - for i := 0; i < 10; i++ { - s.stack = append(s.stack, big.NewInt(int64(i))) + s.push(*uint256.NewInt(uint64(i))) } instr := opSwap(4) instr(s) - assert.Equal(t, five, s.stack[1]) - assert.Equal(t, one, s.stack[6-1]) + assert.Equal(t, *uint256.NewInt(5), s.stack.data[9]) + assert.Equal(t, *uint256.NewInt(9), s.stack.data[5]) } func TestLog(t *testing.T) { @@ -1349,13 +1384,13 @@ func TestLog(t *testing.T) { defer cancelFn() s.msg.Static = true - s.sp = 1 + s.stack.sp = 1 - s.push(big.NewInt(3)) - s.push(big.NewInt(20)) + s.push(*uint256.NewInt(3)) + s.push(*uint256.NewInt(20)) for i := 0; i < 20; i++ { - s.push(big.NewInt(int64(i))) + s.push(*uint256.NewInt(uint64(i))) } instr := opLog(10) @@ -1368,13 +1403,13 @@ func TestLog(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.sp = 1 + s.stack.sp = 1 - s.push(big.NewInt(3)) - s.push(big.NewInt(20)) + s.push(*uint256.NewInt(3)) + s.push(*uint256.NewInt(20)) for i := 0; i < 20; i++ { - s.push(big.NewInt(int64(i))) + s.push(*uint256.NewInt(uint64(i))) } instr := opLog(35) @@ -1389,15 +1424,15 @@ func TestLog(t *testing.T) { s.gas = 25000 - s.push(big.NewInt(3)) - s.push(big.NewInt(20)) + s.push(*uint256.NewInt(3)) + s.push(*uint256.NewInt(20)) mockHost := &mockHost{} mockHost.On("EmitLog", mock.Anything, mock.Anything, mock.Anything).Once() s.host = mockHost for i := 0; i < 20; i++ { - s.push(big.NewInt(int64(i))) + s.push(*uint256.NewInt(uint64(i))) } instr := opLog(10) @@ -1446,6 +1481,25 @@ var ( addr1 = types.StringToAddress("1") ) +func convertBigIntSliceToUint256(bigInts []*big.Int) []uint256.Int { + var uint256s = make([]uint256.Int, 0, len(bigInts)) + + for _, bi := range bigInts { + if bi.Sign() < 0 { + return nil + } + + ui, overflow := uint256.FromBig(bi) + if overflow { + return nil + } + + uint256s = append(uint256s, *ui) + } + + return uint256s +} + func Test_opSload(t *testing.T) { t.Parallel() @@ -1618,15 +1672,15 @@ func Test_opSload(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - t.Parallel() + //t.Parallel() s, closeFn := getState(tt.config) defer closeFn() s.msg = tt.contract s.gas = tt.initState.gas - s.sp = tt.initState.sp - s.stack = tt.initState.stack + s.stack.sp = tt.initState.sp + s.stack.data = convertBigIntSliceToUint256(tt.initState.stack) s.memory = tt.initState.memory s.config = tt.config tt.mockHost.accessList = tt.initState.accessList @@ -1635,8 +1689,8 @@ func Test_opSload(t *testing.T) { opSload(s) assert.Equal(t, tt.resultState.gas, s.gas, "gas in state after execution is not correct") - assert.Equal(t, tt.resultState.sp, s.sp, "sp in state after execution is not correct") - assert.Equal(t, tt.resultState.stack, s.stack, "stack in state after execution is not correct") + assert.Equal(t, tt.resultState.sp, s.stack.sp, "sp in state after execution is not correct") + assert.Equal(t, convertBigIntSliceToUint256(tt.resultState.stack), s.stack.data, "stack in state after execution is not correct") assert.Equal(t, tt.resultState.memory, s.memory, "memory in state after execution is not correct") assert.Equal(t, tt.resultState.accessList, tt.mockHost.accessList, "accesslist in state after execution is not correct") assert.Equal(t, tt.resultState.stop, s.stop, "stop in state after execution is not correct") @@ -1693,8 +1747,6 @@ func TestCreate(t *testing.T) { sp: 1, stack: []*big.Int{ addressToBigInt(crypto.CreateAddress(addr1, 0)), // contract address - big.NewInt(0x00), - big.NewInt(0x00), }, memory: []byte{ byte(REVERT), @@ -1825,8 +1877,6 @@ func TestCreate(t *testing.T) { sp: 1, stack: []*big.Int{ // need to init with 0x01 to add abs field in big.Int - big.NewInt(0x01).SetInt64(0x00), - big.NewInt(0x00), big.NewInt(0x00), }, memory: []byte{ @@ -1877,8 +1927,6 @@ func TestCreate(t *testing.T) { stack: []*big.Int{ // need to init with 0x01 to add abs field in big.Int big.NewInt(0x01).SetInt64(0x00), - big.NewInt(0x00), - big.NewInt(0x00), }, memory: []byte{ byte(REVERT), @@ -1928,10 +1976,7 @@ func TestCreate(t *testing.T) { gas: 15, sp: 1, stack: []*big.Int{ - big.NewInt(0x01).SetInt64(0x00), - big.NewInt(0x01), - big.NewInt(0x00), - big.NewInt(0x00), + big.NewInt(0x0), }, memory: []byte{ byte(REVERT), @@ -1960,8 +2005,8 @@ func TestCreate(t *testing.T) { s.msg = tt.contract s.gas = tt.initState.gas - s.sp = tt.initState.sp - s.stack = tt.initState.stack + s.stack.sp = tt.initState.sp + s.stack.data = convertBigIntSliceToUint256(tt.initState.stack) s.memory = tt.initState.memory s.config = tt.config s.host = tt.mockHost @@ -1969,8 +2014,8 @@ func TestCreate(t *testing.T) { opCreate(tt.op)(s) assert.Equal(t, tt.resultState.gas, s.gas, "gas in state after execution is not correct") - assert.Equal(t, tt.resultState.sp, s.sp, "sp in state after execution is not correct") - assert.Equal(t, tt.resultState.stack, s.stack, "stack in state after execution is not correct") + assert.Equal(t, tt.resultState.sp, s.stack.sp, "sp in state after execution is not correct") + assert.Equal(t, convertBigIntSliceToUint256(tt.resultState.stack), s.stack.data, "stack in state after execution is not correct") assert.Equal(t, tt.resultState.memory, s.memory, "memory in state after execution is not correct") assert.Equal(t, tt.resultState.stop, s.stop, "stop in state after execution is not correct") assert.Equal(t, tt.resultState.err, s.err, "err in state after execution is not correct") @@ -2011,103 +2056,28 @@ func Test_opReturnDataCopy(t *testing.T) { err: errOpCodeNotFound, }, }, - { - name: "should return error if memOffset is negative", - config: &allEnabledForks, - initState: &state{ - stack: []*big.Int{ - big.NewInt(1), // length - big.NewInt(0), // dataOffset - big.NewInt(-1), // memOffset - }, - sp: 3, - returnData: []byte{0xff}, - }, - resultState: &state{ - config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(1), - big.NewInt(0), - big.NewInt(-1), - }, - sp: 0, - returnData: []byte{0xff}, - stop: true, - err: errReturnDataOutOfBounds, - }, - }, - { - name: "should return error if dataOffset is negative", - config: &allEnabledForks, - initState: &state{ - stack: []*big.Int{ - big.NewInt(1), // length - big.NewInt(-1), // dataOffset - big.NewInt(0), // memOffset - }, - sp: 3, - memory: make([]byte, 1), - }, - resultState: &state{ - config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(1), - big.NewInt(-1), - big.NewInt(0), - }, - sp: 0, - memory: make([]byte, 1), - stop: true, - err: errReturnDataOutOfBounds, - }, - }, - { - name: "should return error if length is negative", - config: &allEnabledForks, - initState: &state{ - stack: []*big.Int{ - big.NewInt(-1), // length - big.NewInt(2), // dataOffset - big.NewInt(0), // memOffset - }, - sp: 3, - returnData: []byte{0xff}, - }, - resultState: &state{ - config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(-1), - big.NewInt(2), - big.NewInt(0), - }, - sp: 0, - returnData: []byte{0xff}, - stop: true, - err: errReturnDataOutOfBounds, - }, - }, { name: "should copy data from returnData to memory", config: &allEnabledForks, initState: &state{ - stack: []*big.Int{ - big.NewInt(1), // length - big.NewInt(0), // dataOffset - big.NewInt(0), // memOffset + stack: OptimizedStack{ + data: []uint256.Int{ + *uint256.NewInt(1), // length + *uint256.NewInt(0), // dataOffset + *uint256.NewInt(0), // memOffset + }, + sp: 3, }, - sp: 3, returnData: []byte{0xff}, memory: []byte{0x0}, gas: 10, }, resultState: &state{ config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(1), - big.NewInt(0), - big.NewInt(0), + stack: OptimizedStack{ + data: []uint256.Int{}, + sp: 0, }, - sp: 0, returnData: []byte{0xff}, memory: []byte{0xff}, gas: 7, @@ -2122,96 +2092,50 @@ func Test_opReturnDataCopy(t *testing.T) { name: "should not copy data if length is zero", config: &allEnabledForks, initState: &state{ - stack: []*big.Int{ - big.NewInt(0), // length - big.NewInt(0), // dataOffset - big.NewInt(4), // memOffset + stack: OptimizedStack{ + data: []uint256.Int{ + *uint256.NewInt(0), // length + *uint256.NewInt(0), // dataOffset + *uint256.NewInt(4), // memOffset + }, + sp: 3, }, - sp: 3, returnData: []byte{0x01}, memory: []byte{0x02}, }, resultState: &state{ config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(0), - big.NewInt(0), - big.NewInt(4), + stack: OptimizedStack{ + data: []uint256.Int{}, + sp: 0, }, - sp: 0, returnData: []byte{0x01}, memory: []byte{0x02}, stop: false, err: nil, }, }, - { - name: "should return error if data offset overflows uint64", - config: &allEnabledForks, - initState: &state{ - stack: []*big.Int{ - big.NewInt(1), // length - bigIntValue, // dataOffset - big.NewInt(-1), // memOffset - }, - sp: 3, - }, - resultState: &state{ - config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(1), - bigIntValue, - big.NewInt(-1), - }, - sp: 0, - stop: true, - err: errReturnDataOutOfBounds, - }, - }, - { - name: "should return error if sum of data offset and length overflows uint64", - config: &allEnabledForks, - initState: &state{ - stack: []*big.Int{ - bigIntValue2, // length - bigIntValue2, // dataOffset - big.NewInt(-1), // memOffset - }, - sp: 3, - }, - resultState: &state{ - config: &allEnabledForks, - stack: []*big.Int{ - bigIntValue2, - bigIntValue2, - big.NewInt(-1), - }, - sp: 0, - stop: true, - err: errReturnDataOutOfBounds, - }, - }, { name: "should return error if the length of return data does not have enough space to receive offset + length bytes", config: &allEnabledForks, initState: &state{ - stack: []*big.Int{ - big.NewInt(2), // length - big.NewInt(0), // dataOffset - big.NewInt(0), // memOffset + stack: OptimizedStack{ + data: []uint256.Int{ + *uint256.NewInt(2), // length + *uint256.NewInt(0), // dataOffset + *uint256.NewInt(0), // memOffset + }, + sp: 3, }, - sp: 3, returnData: []byte{0xff}, memory: []byte{0x0}, }, resultState: &state{ config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(2), - big.NewInt(0), - big.NewInt(0), + stack: OptimizedStack{ + data: []uint256.Int{}, + sp: 0, }, - sp: 0, returnData: []byte{0xff}, memory: []byte{0x0}, stop: true, @@ -2222,24 +2146,24 @@ func Test_opReturnDataCopy(t *testing.T) { name: "should return error if there is no gas", config: &allEnabledForks, initState: &state{ - stack: []*big.Int{ - big.NewInt(1), // length - big.NewInt(0), // dataOffset - big.NewInt(0), // memOffset + stack: OptimizedStack{ + data: []uint256.Int{ + *uint256.NewInt(1), // length + *uint256.NewInt(0), // dataOffset + *uint256.NewInt(0), // memOffset + }, + sp: 3, }, - sp: 3, returnData: []byte{0xff}, memory: []byte{0x0}, gas: 0, }, resultState: &state{ config: &allEnabledForks, - stack: []*big.Int{ - big.NewInt(1), - big.NewInt(0), - big.NewInt(0), + stack: OptimizedStack{ + data: []uint256.Int{}, + sp: 0, }, - sp: 0, returnData: []byte{0xff}, memory: []byte{0x0}, gas: 0, @@ -2260,7 +2184,7 @@ func Test_opReturnDataCopy(t *testing.T) { defer closeFn() state.gas = test.initState.gas - state.sp = test.initState.sp + state.stack.sp = test.initState.stack.sp state.stack = test.initState.stack state.memory = test.initState.memory state.returnData = test.initState.returnData @@ -2287,7 +2211,7 @@ func Test_opReturnDataCopy(t *testing.T) { // to suite future needs. func CompareStates(a *state, b *state) bool { // Compare simple fields - if a.ip != b.ip || a.lastGasCost != b.lastGasCost || a.sp != b.sp || !errors.Is(a.err, b.err) || a.stop != b.stop || a.gas != b.gas { + if a.ip != b.ip || a.lastGasCost != b.lastGasCost || a.stack.sp != b.stack.sp || !errors.Is(a.err, b.err) || a.stop != b.stop || a.gas != b.gas { return false } @@ -2297,12 +2221,12 @@ func CompareStates(a *state, b *state) bool { } // Deep comparison of stacks - if len(a.stack) != len(b.stack) { + if len(a.stack.data) != len(b.stack.data) { return false } - for i := range a.stack { - if a.stack[i].Cmp(b.stack[i]) != 0 { + for i := range a.stack.data { + if a.stack.data[i] != b.stack.data[i] { return false } } @@ -2332,15 +2256,16 @@ func Test_opCall(t *testing.T) { config: allEnabledForks, initState: &state{ gas: 2600, - sp: 6, - stack: []*big.Int{ - big.NewInt(0x00), // outSize - big.NewInt(0x02), // outOffset - big.NewInt(0x00), // inSize - big.NewInt(0x00), // inOffset - big.NewInt(0x00), // address - big.NewInt(0x00), // initialGas - }, + stack: OptimizedStack{ + data: []uint256.Int{ + *uint256.NewInt(0x00), // outSize + *uint256.NewInt(0x02), // outOffset + *uint256.NewInt(0x00), // inSize + *uint256.NewInt(0x00), // inOffset + *uint256.NewInt(0x00), // address + *uint256.NewInt(0x00), // initialGas + }, + sp: 6}, memory: []byte{0x01}, }, resultState: &state{ @@ -2357,74 +2282,6 @@ func Test_opCall(t *testing.T) { }, }, }, - // { - // name: "call cost overflow (EIP150 fork disabled)", - // op: CALLCODE, - // contract: &runtime.Contract{ - // Static: false, - // }, - // config: chain.AllForksEnabled.RemoveFork(chain.EIP150).At(0), - // initState: &state{ - // gas: 6640, - // sp: 7, - // stack: []*big.Int{ - // big.NewInt(0x00), // outSize - // big.NewInt(0x00), // outOffset - // big.NewInt(0x00), // inSize - // big.NewInt(0x00), // inOffset - // big.NewInt(0x01), // value - // big.NewInt(0x03), // address - // big.NewInt(0).SetUint64(math.MaxUint64), // initialGas - // }, - // memory: []byte{0x01}, - // accessList: runtime.NewAccessList(), - // }, - // resultState: &state{ - // memory: []byte{0x01}, - // stop: true, - // err: errGasUintOverflow, - // gas: 6640, - // }, - // mockHost: &mockHostForInstructions{ - // callxResult: &runtime.ExecutionResult{ - // ReturnValue: []byte{0x03}, - // }, - // }, - // }, - // { - // name: "available gas underflow", - // op: CALLCODE, - // contract: &runtime.Contract{ - // Static: false, - // }, - // config: allEnabledForks, - // initState: &state{ - // gas: 6640, - // sp: 7, - // stack: []*big.Int{ - // big.NewInt(0x00), // outSize - // big.NewInt(0x00), // outOffset - // big.NewInt(0x00), // inSize - // big.NewInt(0x00), // inOffset - // big.NewInt(0x01), // value - // big.NewInt(0x03), // address - // big.NewInt(0).SetUint64(math.MaxUint64), // initialGas - // }, - // memory: []byte{0x01}, - // accessList: runtime.NewAccessList(), - // }, - // resultState: &state{ - // memory: []byte{0x01}, - // stop: true, - // err: errOutOfGas, - // gas: 6640, - // }, - // mockHost: &mockHostForInstructions{ - // callxResult: &runtime.ExecutionResult{ - // ReturnValue: []byte{0x03}, - // }, - // }, - // }, } for _, tt := range tests { @@ -2437,7 +2294,7 @@ func Test_opCall(t *testing.T) { state.gas = test.initState.gas state.msg = test.contract - state.sp = test.initState.sp + state.stack.sp = test.initState.stack.sp state.stack = test.initState.stack state.memory = test.initState.memory state.config = &test.config diff --git a/state/runtime/evm/optimized_stack.go b/state/runtime/evm/optimized_stack.go new file mode 100644 index 0000000000..1a9933df73 --- /dev/null +++ b/state/runtime/evm/optimized_stack.go @@ -0,0 +1,74 @@ +package evm + +import ( + "github.com/0xPolygon/polygon-edge/state/runtime" + "github.com/holiman/uint256" +) + +// OptimizedStack represents a stack data structure for uint256 integers. +// It utilizes a dynamic array (slice) to store the data and an integer (sp) +// to keep track of the current stack pointer. +// OptimizedStack uint256 integers for improved operations on values on the +// stack and minimizes heap allocations. +// TODO: Check if sp field can be removed. +type OptimizedStack struct { + sp int // Stack pointer to track the top of the stack + data []uint256.Int // Slice to store the stack's elements +} + +// reset clears the stack by resetting the stack pointer to 0 and truncating +// the data slice to zero length. +func (s *OptimizedStack) reset() { + s.sp = 0 + s.data = s.data[:0] // Efficiently clears the slice without allocating new memory +} + +// push adds a new element of type uint256.Int to the top of the stack. +// It appends the element to the data slice and increments the stack pointer. +func (s *OptimizedStack) push(val uint256.Int) { + s.data = append(s.data, val) + s.sp++ +} + +// pop removes and returns the top element of the stack. +// If the stack is empty, it returns a zero value of uint256.Int and an error. +func (s *OptimizedStack) pop() (uint256.Int, error) { + if s.sp == 0 { + // The stack is empty, return a zero value and an underflow error + return *new(uint256.Int), &runtime.StackUnderflowError{} + } + + o := s.data[s.sp-1] // Get the top element + s.sp-- // Decrement the stack pointer + s.data = s.data[:s.sp] // Truncate the slice to remove the top element + + return o, nil +} + +// top returns the top element of the stack without removing it. If the stack +// is empty, it returns nil and an error. +func (s *OptimizedStack) top() (*uint256.Int, error) { + if s.sp == 0 { + // The stack is empty, return nil and an underflow error + return nil, &runtime.StackUnderflowError{} + } + + topIndex := len(s.data) - 1 // Calculate the index of the top element + + return &s.data[topIndex], nil // Return a pointer to the top element +} + +// peekAt returns the element at the nth position from the top of the stack, +// without modifying the stack. It does not perform bounds checking and it +// returns the value of the element, not the reference. +// TODO: Check on error handling +func (s *OptimizedStack) peekAt(n int) uint256.Int { + return s.data[s.sp-n] +} + +// swap exchanges the top element of the stack with the element at the n-th position +// from the top. It does not perform bounds checking and assumes valid input. +// TODO: Check on error handling +func (s *OptimizedStack) swap(n int) { + s.data[s.sp-1], s.data[s.sp-n-1] = s.data[s.sp-n-1], s.data[s.sp-1] +} diff --git a/state/runtime/evm/optimized_stack_test.go b/state/runtime/evm/optimized_stack_test.go new file mode 100644 index 0000000000..19d856f176 --- /dev/null +++ b/state/runtime/evm/optimized_stack_test.go @@ -0,0 +1,121 @@ +package evm + +import ( + "testing" + + "github.com/holiman/uint256" +) + +// TestPushPop tests the push and pop operations of the stack. +func TestOptimizedStackPushPop(t *testing.T) { + var stack OptimizedStack + + value := uint256.NewInt(10) + + stack.push(*value) + + if stack.sp != 1 { + t.Errorf("Expected stack pointer to be 1, got %d", stack.sp) + } + + poppedValue, err := stack.pop() + + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + if poppedValue != *value { + t.Errorf("Expected popped value to be %v, got %v", value, poppedValue) + } + + if stack.sp != 0 { + t.Errorf("Expected stack pointer to be 0 after pop, got %d", stack.sp) + } +} + +// TestUnderflow tests the underflow condition when popping from an empty stack. +func TestOptimizedStackUnderflow(t *testing.T) { + var stack OptimizedStack + + _, err := stack.pop() + if err == nil { + t.Errorf("Expected an underflow error when popping from an empty stack, got nil") + } +} + +// TestTop tests the top function without modifying the stack. +func TestOptimizedStackTop(t *testing.T) { + var stack OptimizedStack + + value := uint256.NewInt(10) + + stack.push(*value) + + topValue, err := stack.top() + + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + if *topValue != *value { + t.Errorf("Expected top value to be %v, got %v", value, *topValue) + } + + if stack.sp != 1 { + t.Errorf("Expected stack pointer to remain 1 after top, got %d", stack.sp) + } +} + +// TestReset tests the reset function to ensure it clears the stack. +func TestOptimizedStackReset(t *testing.T) { + var stack OptimizedStack + + stack.push(*uint256.NewInt(0)) + stack.reset() + + if stack.sp != 0 || len(stack.data) != 0 { + t.Errorf("Expected stack to be empty after reset, got sp: %d, len(data): %d", stack.sp, len(stack.data)) + } +} + +// TestPeekAt tests the peekAt function for retrieving elements without modifying the stack. +func TestOptimizedStackPeekAt(t *testing.T) { + var stack OptimizedStack + + value1 := uint256.NewInt(1) + value2 := uint256.NewInt(2) + + stack.push(*value1) + stack.push(*value2) + + peekedValue := stack.peekAt(2) + + if peekedValue != *value1 { + t.Errorf("Expected to peek at value %v, got %v", value1, peekedValue) + } + + // Verify stack state hasn't changed after peekAt + if stack.sp != 2 { + t.Errorf("Expected stack pointer to remain 2 after peekAt, got %d", stack.sp) + } +} + +// TestSwap tests the swap function to ensure it correctly swaps elements in the stack. +func TestOptimizedStackSwap(t *testing.T) { + var stack OptimizedStack + + value1 := uint256.NewInt(1) + value2 := uint256.NewInt(2) + + // Push two distinct values onto the stack + stack.push(*value1) + stack.push(*value2) + + // Swap the top two elements + stack.swap(1) + + // Verify swap operation + if stack.data[stack.sp-1] != *value1 || stack.data[stack.sp-2] != *value2 { + t.Errorf("Expected top two values to be swapped to %v and %v, got %v and %v", value1, value2, stack.data[stack.sp-1], stack.data[stack.sp-2]) + } +} diff --git a/state/runtime/evm/state.go b/state/runtime/evm/state.go index 8f6fa2ebd0..afa484274f 100644 --- a/state/runtime/evm/state.go +++ b/state/runtime/evm/state.go @@ -12,6 +12,7 @@ import ( "github.com/0xPolygon/polygon-edge/helper/hex" "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" + "github.com/holiman/uint256" ) var statePool = sync.Pool{ @@ -46,8 +47,6 @@ var ( errReturnDataOutOfBounds = errors.New("return data out of bounds") ) -// Instructions is the code of instructions - type state struct { ip int code []byte @@ -62,8 +61,7 @@ type state struct { lastGasCost uint64 // stack - stack []*big.Int - sp int + stack OptimizedStack err error stop bool @@ -76,12 +74,9 @@ type state struct { returnData []byte ret []byte - - unsafepool common.UnsafePool[*big.Int] } func (c *state) reset() { - c.sp = 0 c.ip = 0 c.gas = 0 c.currentConsumedGas = 0 @@ -97,14 +92,7 @@ func (c *state) reset() { c.memory[i] = 0 } - // Before stack cleanup, return instances of big.Int to the pool - // for the future usage - for i := range c.stack { - c.unsafepool.Put(func(x *big.Int) *big.Int { - return x.SetInt64(0) - }, c.stack[i]) - } - c.stack = c.stack[:0] + c.stack.reset() c.tmp = c.tmp[:0] c.ret = c.ret[:0] c.code = c.code[:0] @@ -134,38 +122,24 @@ func (c *state) exit(err error) { c.err = err } -func (c *state) push(val *big.Int) { - c.push1().Set(val) -} - -func (c *state) push1() *big.Int { - if len(c.stack) > c.sp { - c.sp++ - - return c.stack[c.sp-1] - } - - v := c.unsafepool.Get(func() *big.Int { - return big.NewInt(0) - }) - - c.stack = append(c.stack, v) - c.sp++ - - return v +func (c *state) push(val uint256.Int) { + c.stack.push(val) } func (c *state) stackAtLeast(n int) bool { - return c.sp >= n + return c.stack.sp >= n } func (c *state) popHash() types.Hash { - return types.BytesToHash(c.pop().Bytes()) + v := c.pop() + v.Bytes() + + return types.BytesToHash(v.Bytes()) } func (c *state) popAddr() (types.Address, bool) { - b := c.pop() - if b == nil { + b, err := c.stack.pop() + if err != nil { return types.Address{}, false } @@ -173,34 +147,27 @@ func (c *state) popAddr() (types.Address, bool) { } func (c *state) stackSize() int { - return c.sp + return c.stack.sp } -func (c *state) top() *big.Int { - if c.sp == 0 { - return nil - } +func (c *state) top() *uint256.Int { + v, _ := c.stack.top() - return c.stack[c.sp-1] + return v } -func (c *state) pop() *big.Int { - if c.sp == 0 { - return nil - } - - o := c.stack[c.sp-1] - c.sp-- +func (c *state) pop() uint256.Int { + v, _ := c.stack.pop() - return o + return v } -func (c *state) peekAt(n int) *big.Int { - return c.stack[c.sp-n] +func (c *state) peekAt(n int) uint256.Int { + return c.stack.peekAt(n) } func (c *state) swap(n int) { - c.stack[c.sp-1], c.stack[c.sp-n-1] = c.stack[c.sp-n-1], c.stack[c.sp-1] + c.stack.swap(n) } func (c *state) consumeGas(gas uint64) bool { @@ -230,11 +197,16 @@ func (c *state) Run() ([]byte, error) { ok bool ) + tracer := c.host.GetTracer() + iterationCount := 0 + for !c.stop { op, ok = c.CurrentOpCode() gasCopy, ipCopy := c.gas, uint64(c.ip) - c.captureState(int(op)) + if tracer != nil { + c.captureState(int(op)) + } if !ok { c.Halt() @@ -251,8 +223,8 @@ func (c *state) Run() ([]byte, error) { } // check if the depth of the stack is enough for the instruction - if c.sp < inst.stack { - c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: inst.stack}) + if c.stack.sp < inst.stack { + c.exit(&runtime.StackUnderflowError{StackLen: c.stack.sp, Required: inst.stack}) c.captureExecution(op.String(), uint64(c.ip), gasCopy, inst.gas) break @@ -269,17 +241,18 @@ func (c *state) Run() ([]byte, error) { // execute the instruction inst.inst(c) - if c.host.GetTracer() != nil { + if tracer != nil { c.captureExecution(op.String(), ipCopy, gasCopy, gasCopy-c.gas) } // check if stack size exceeds the max size - if c.sp > stackSize { - c.exit(&runtime.StackOverflowError{StackLen: c.sp, Limit: stackSize}) + if c.stack.sp > stackSize { + c.exit(&runtime.StackOverflowError{StackLen: c.stack.sp, Limit: stackSize}) break } c.ip++ + iterationCount++ } if err := c.err; err != nil { @@ -304,7 +277,8 @@ func (c *state) Len() int { // allocateMemory allocates memory to enable accessing in the range of [offset, offset+size] // throws error if the given offset and size are negative // consumes gas if memory needs to be expanded -func (c *state) allocateMemory(offset, size *big.Int) bool { +// func (c *state) allocateMemory(offset, size *big.Int) bool { +func (c *state) allocateMemory(offset, size uint256.Int) bool { if !offset.IsUint64() || !size.IsUint64() { c.exit(errReturnDataOutOfBounds) @@ -343,7 +317,7 @@ func (c *state) allocateMemory(offset, size *big.Int) bool { return true } -func (c *state) get2(dst []byte, offset, length *big.Int) ([]byte, bool) { +func (c *state) get2(dst []byte, offset, length uint256.Int) ([]byte, bool) { if length.Sign() == 0 { return nil, true } @@ -389,12 +363,20 @@ func (c *state) captureState(opCode int) { return } + bigIntArray := make([]*big.Int, 0, len(c.stack.data)) + + for _, num := range c.stack.data { + // Convert uint256 to *big.Int and append to bigIntArray as temp solution + bigNum := num.ToBig() // Adjust conversion based on your uint256 implementation + bigIntArray = append(bigIntArray, bigNum) + } + tracer.CaptureState( c.memory, - c.stack, + bigIntArray, opCode, c.msg.Address, - c.sp, + c.stack.sp, c.host, c, ) diff --git a/state/runtime/evm/state_test.go b/state/runtime/evm/state_test.go index 5a5892238d..320b34d5fc 100644 --- a/state/runtime/evm/state_test.go +++ b/state/runtime/evm/state_test.go @@ -5,6 +5,7 @@ import ( "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/state/runtime" + "github.com/holiman/uint256" "github.com/stretchr/testify/assert" ) @@ -47,10 +48,10 @@ func TestStackTop(t *testing.T) { s, closeFn := getState(&chain.ForksInTime{}) defer closeFn() - s.push(one) - s.push(two) + s.push(*uint256.NewInt(1)) + s.push(*uint256.NewInt(2)) - assert.Equal(t, two, s.top()) + assert.Equal(t, *uint256.NewInt(2), *s.top()) assert.Equal(t, s.stackSize(), 2) } From e27a57ef6d73a3ece4eaf67dd20874a3a5649d15 Mon Sep 17 00:00:00 2001 From: Mita Date: Fri, 15 Mar 2024 23:47:13 +0100 Subject: [PATCH 02/13] Replacing big.int with uint256 for jump instruction. --- state/runtime/evm/instructions.go | 8 ++++---- state/runtime/evm/state.go | 11 ++++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index dfb490c58b..9b4ab35471 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -327,7 +327,6 @@ func opSar(c *state) { // memory operations func opMLoad(c *state) { v := c.top() - //offset := v.ToBig() var ok bool c.tmp, ok = c.get2(c.tmp[:0], *v, *wordSize256) @@ -392,7 +391,7 @@ func opSload(c *state) { return } - val := c.host.GetStorage(c.msg.Address, bigToHash(loc.ToBig())) + val := c.host.GetStorage(c.msg.Address, uint256ToHash(loc)) loc.SetBytes(val.Bytes()) } @@ -928,7 +927,8 @@ func opSelfDestruct(c *state) { } func opJump(c *state) { - if dest := c.pop(); c.validJumpdest(dest.ToBig()) { + dest := c.pop() + if c.validJumpdest(dest) { c.ip = int(dest.Uint64() - 1) } else { c.exit(errInvalidJump) @@ -940,7 +940,7 @@ func opJumpi(c *state) { cond := c.pop() if cond.Sign() != 0 { - if c.validJumpdest(dest.ToBig()) { + if c.validJumpdest(dest) { c.ip = int(dest.Uint64() - 1) } else { c.exit(errInvalidJump) diff --git a/state/runtime/evm/state.go b/state/runtime/evm/state.go index afa484274f..24deaaa22e 100644 --- a/state/runtime/evm/state.go +++ b/state/runtime/evm/state.go @@ -100,9 +100,10 @@ func (c *state) reset() { c.memory = c.memory[:0] } -func (c *state) validJumpdest(dest *big.Int) bool { - udest := dest.Uint64() - if dest.BitLen() >= 63 || udest >= uint64(len(c.code)) { +func (c *state) validJumpdest(dest uint256.Int) bool { + udest, overflow := dest.Uint64WithOverflow() + + if overflow || udest >= uint64(len(c.code)) { return false } @@ -266,6 +267,10 @@ func (c *state) inStaticCall() bool { return c.msg.Static } +func uint256ToHash(b *uint256.Int) types.Hash { + return types.BytesToHash(b.Bytes()) +} + func bigToHash(b *big.Int) types.Hash { return types.BytesToHash(b.Bytes()) } From 7640c4e2f6d5823870f6becbf773f785c520c6b6 Mon Sep 17 00:00:00 2001 From: cokicm Date: Tue, 19 Mar 2024 21:03:41 +0100 Subject: [PATCH 03/13] Update state/runtime/evm/instructions.go Co-authored-by: Goran Rojovic <100121253+goran-ethernal@users.noreply.github.com> --- state/runtime/evm/instructions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 9b4ab35471..bce81a5e1c 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -109,7 +109,7 @@ func opMod(c *state) { a := c.pop() b := c.top() - b = b.Mod(&a, b) + b.Mod(&a, b) } func opSMod(c *state) { From 2535c38eb43ab187b5eba8262c78aae16113f47e Mon Sep 17 00:00:00 2001 From: Mita Date: Tue, 19 Mar 2024 22:56:30 +0100 Subject: [PATCH 04/13] Code review fixes. --- state/runtime/evm/instructions.go | 28 +++---- state/runtime/evm/instructions_test.go | 95 ++++++++++++----------- state/runtime/evm/optimized_stack_test.go | 49 ++++-------- state/runtime/evm/state.go | 4 - 4 files changed, 74 insertions(+), 102 deletions(-) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index bce81a5e1c..9a934eb2e4 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -135,7 +135,7 @@ func opExp(c *state) { return } - y = y.Exp(&x, y) + y.Exp(&x, y) } func opAddMod(c *state) { @@ -143,11 +143,7 @@ func opAddMod(c *state) { b := c.pop() z := c.top() - if z.IsZero() { - z.SetUint64(0) - } else { - z.AddMod(&a, &b, z) - } + z.AddMod(&a, &b, z) } func opMulMod(c *state) { @@ -155,12 +151,7 @@ func opMulMod(c *state) { b := c.pop() z := c.top() - if z.IsZero() { - // division by zero - z.SetUint64(0) - } else { - z = z.MulMod(&a, &b, z) - } + z = z.MulMod(&a, &b, z) } func opAnd(c *state) { @@ -371,10 +362,10 @@ func opSload(c *state) { var gas uint64 if c.config.Berlin { - if _, slotPresent := c.host.ContainsAccessListSlot(c.msg.Address, bigToHash(loc.ToBig())); !slotPresent { + if _, slotPresent := c.host.ContainsAccessListSlot(c.msg.Address, uint256ToHash(loc)); !slotPresent { gas = ColdStorageReadCostEIP2929 - c.host.AddSlotToAccessList(c.msg.Address, bigToHash(loc.ToBig())) + c.host.AddSlotToAccessList(c.msg.Address, uint256ToHash(loc)) } else { gas = WarmStorageReadCostEIP2929 } @@ -827,7 +818,7 @@ func opCodeCopy(c *state) { } } -// block information< +// block information func opBlockHash(c *state) { num := c.top() @@ -966,16 +957,15 @@ func opPush(n int) instruction { ins := c.code ip := c.ip + d := uint256.NewInt(0) if ip+1+n > len(ins) { - d := uint256.NewInt(0) d.SetBytes(append(ins[ip+1:], make([]byte, n)...)) - c.push(*d) } else { - d := uint256.NewInt(0) d.SetBytes(ins[ip+1 : ip+1+n]) - c.push(*d) } + c.push(*d) + c.ip += n } } diff --git a/state/runtime/evm/instructions_test.go b/state/runtime/evm/instructions_test.go index ea85679369..e573f56570 100644 --- a/state/runtime/evm/instructions_test.go +++ b/state/runtime/evm/instructions_test.go @@ -25,6 +25,11 @@ var ( allEnabledForks = chain.AllForksEnabled.At(0) ) +var ( + zero256 = *uint256.NewInt(0) + one256 = *uint256.NewInt(1) +) + type OperandsLogical struct { operands []*big.Int expectedResult bool @@ -543,8 +548,8 @@ func TestMStore(t *testing.T) { s, closeFn := getState(&chain.ForksInTime{}) defer closeFn() - s.push(*uint256.NewInt(1)) // value - s.push(*offset) // offset + s.push(one256) // value + s.push(*offset) // offset opMStore(s) @@ -563,8 +568,8 @@ func TestMStore8(t *testing.T) { s, closeFn := getState(&chain.ForksInTime{}) defer closeFn() - s.push(*uint256.NewInt(1)) //value - s.push(*offsetStore) //offset + s.push(one256) //value + s.push(*offsetStore) //offset opMStore8(s) @@ -585,7 +590,7 @@ func TestSload(t *testing.T) { mockHost.On("GetStorage", mock.Anything, mock.Anything).Return(bigToHash(one)).Once() s.host = mockHost - s.push(*uint256.NewInt(1)) + s.push(one256) opSload(s) assert.Equal(t, uint64(200), s.gas) @@ -601,7 +606,7 @@ func TestSload(t *testing.T) { mockHost.On("GetStorage", mock.Anything, mock.Anything).Return(bigToHash(one)).Once() s.host = mockHost - s.push(*uint256.NewInt(1)) + s.push(one256) opSload(s) assert.Equal(t, uint64(800), s.gas) @@ -617,7 +622,7 @@ func TestSload(t *testing.T) { mockHost.On("GetStorage", mock.Anything, mock.Anything).Return(bigToHash(one)).Once() s.host = mockHost - s.push(*uint256.NewInt(1)) + s.push(one256) opSload(s) assert.Equal(t, uint64(950), s.gas) @@ -633,7 +638,7 @@ func TestSStore(t *testing.T) { }) defer closeFn() - s.push(*uint256.NewInt(1)) + s.push(one256) opSStore(s) assert.True(t, s.stop) @@ -653,8 +658,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageUnchanged).Once() s.host = mockHost - s.push(*uint256.NewInt(1)) - s.push(*uint256.NewInt(0)) + s.push(one256) + s.push(zero256) opSStore(s) assert.Equal(t, uint64(9200), s.gas) @@ -673,8 +678,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageModified).Once() s.host = mockHost - s.push(*uint256.NewInt(1)) - s.push(*uint256.NewInt(0)) + s.push(one256) + s.push(zero256) opSStore(s) assert.Equal(t, uint64(5000), s.gas) @@ -690,8 +695,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageAdded).Once() s.host = mockHost - s.push(*uint256.NewInt(1)) - s.push(*uint256.NewInt(0)) + s.push(one256) + s.push(zero256) opSStore(s) assert.Equal(t, uint64(5000), s.gas) @@ -710,8 +715,8 @@ func TestSStore(t *testing.T) { mock.Anything, mock.Anything).Return(runtime.StorageDeleted).Once() s.host = mockHost - s.push(*uint256.NewInt(1)) - s.push(*uint256.NewInt(0)) + s.push(one256) + s.push(zero256) opSStore(s) assert.Equal(t, uint64(5000), s.gas) @@ -894,7 +899,7 @@ func TestCallDataLoad(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(*uint256.NewInt(1)) + s.push(one256) s.msg = &runtime.Contract{Input: big.NewInt(7).Bytes()} @@ -933,7 +938,7 @@ func TestExtCodeSize(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{EIP150: true}) defer cancelFn() - s.push(*uint256.NewInt(1)) + s.push(one256) mockHost := &mockHost{} mockHost.On("GetCodeSize", types.StringToAddress("0x1")).Return(codeSize).Once() @@ -951,7 +956,7 @@ func TestExtCodeSize(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(*uint256.NewInt(1)) + s.push(one256) mockHost := &mockHost{} mockHost.On("GetCodeSize", types.StringToAddress("0x1")).Return(codeSize).Once() @@ -1017,7 +1022,7 @@ func TestExtCodeHash(t *testing.T) { }) defer cancelFn() - s.push(*uint256.NewInt(1)) + s.push(one256) mockHost := &mockHost{} mockHost.On("Empty", types.StringToAddress("0x1")).Return(false).Once() @@ -1039,7 +1044,7 @@ func TestExtCodeHash(t *testing.T) { }) defer cancelFn() - s.push(*uint256.NewInt(1)) + s.push(one256) mockHost := &mockHost{} mockHost.On("Empty", mock.Anything).Return(true).Once() @@ -1055,7 +1060,7 @@ func TestExtCodeHash(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(*uint256.NewInt(1)) + s.push(one256) mockHost := &mockHost{} mockHost.On("Empty", mock.Anything).Return(true).Once() @@ -1110,8 +1115,8 @@ func TestExtCodeCopy(t *testing.T) { mockHost.On("GetCode", mock.Anything).Return("0x1").Once() s.host = mockHost - s.push(*uint256.NewInt(1)) - s.push(*uint256.NewInt(0)) + s.push(one256) + s.push(zero256) s.push(*uint256.NewInt(31)) s.push(*uint256.NewInt(32)) @@ -1130,8 +1135,8 @@ func TestExtCodeCopy(t *testing.T) { mockHost.On("GetCode", mock.Anything).Return("0x1").Once() s.host = mockHost - s.push(*uint256.NewInt(1)) - s.push(*uint256.NewInt(0)) + s.push(one256) + s.push(zero256) s.push(*uint256.NewInt(31)) s.push(*uint256.NewInt(32)) @@ -1150,8 +1155,8 @@ func TestCallDataCopy(t *testing.T) { s.msg.Input = one.Bytes() - s.push(*uint256.NewInt(1)) - s.push(*uint256.NewInt(0)) + s.push(one256) + s.push(zero256) s.push(*uint256.NewInt(31)) opCallDataCopy(s) @@ -1166,9 +1171,9 @@ func TestCodeCopyLenZero(t *testing.T) { var expectedGas = s.gas - s.push(*uint256.NewInt(0)) //length - s.push(*uint256.NewInt(0)) //dataOffset - s.push(*uint256.NewInt(0)) //memOffset + s.push(zero256) //length + s.push(zero256) //dataOffset + s.push(zero256) //memOffset opCodeCopy(s) @@ -1181,8 +1186,8 @@ func TestCodeCopy(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(*uint256.NewInt(1)) //length - s.push(*uint256.NewInt(0)) //dataOffset + s.push(one256) //length + s.push(zero256) //dataOffset s.push(*uint256.NewInt(31)) //memOffset s.code = one.Bytes() @@ -1307,7 +1312,7 @@ func TestSelfDestruct(t *testing.T) { s.msg.Address = types.StringToAddress("0x2") s.gas = 100000 - s.push(*uint256.NewInt(1)) + s.push(one256) mockHost := &mockHost{} mockHost.On("Empty", addr).Return(true).Once() @@ -1340,7 +1345,7 @@ func TestJumpI(t *testing.T) { s.code = make([]byte, 10) s.bitmap = bitmap{big.NewInt(255).Bytes()} - s.push(*uint256.NewInt(1)) + s.push(one256) s.push(*uint256.NewInt(5)) opJumpi(s) @@ -2062,9 +2067,9 @@ func Test_opReturnDataCopy(t *testing.T) { initState: &state{ stack: OptimizedStack{ data: []uint256.Int{ - *uint256.NewInt(1), // length - *uint256.NewInt(0), // dataOffset - *uint256.NewInt(0), // memOffset + one256, // length + zero256, // dataOffset + zero256, // memOffset }, sp: 3, }, @@ -2094,8 +2099,8 @@ func Test_opReturnDataCopy(t *testing.T) { initState: &state{ stack: OptimizedStack{ data: []uint256.Int{ - *uint256.NewInt(0), // length - *uint256.NewInt(0), // dataOffset + zero256, // length + zero256, // dataOffset *uint256.NewInt(4), // memOffset }, sp: 3, @@ -2122,8 +2127,8 @@ func Test_opReturnDataCopy(t *testing.T) { stack: OptimizedStack{ data: []uint256.Int{ *uint256.NewInt(2), // length - *uint256.NewInt(0), // dataOffset - *uint256.NewInt(0), // memOffset + zero256, // dataOffset + zero256, // memOffset }, sp: 3, }, @@ -2148,9 +2153,9 @@ func Test_opReturnDataCopy(t *testing.T) { initState: &state{ stack: OptimizedStack{ data: []uint256.Int{ - *uint256.NewInt(1), // length - *uint256.NewInt(0), // dataOffset - *uint256.NewInt(0), // memOffset + one256, // length + zero256, // dataOffset + zero256, // memOffset }, sp: 3, }, diff --git a/state/runtime/evm/optimized_stack_test.go b/state/runtime/evm/optimized_stack_test.go index 19d856f176..0d6109606a 100644 --- a/state/runtime/evm/optimized_stack_test.go +++ b/state/runtime/evm/optimized_stack_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/holiman/uint256" + "github.com/stretchr/testify/require" ) // TestPushPop tests the push and pop operations of the stack. @@ -20,17 +21,11 @@ func TestOptimizedStackPushPop(t *testing.T) { poppedValue, err := stack.pop() - if err != nil { - t.Errorf("Expected no error, got %v", err) - } + require.NoError(t, err) - if poppedValue != *value { - t.Errorf("Expected popped value to be %v, got %v", value, poppedValue) - } + require.Equal(t, poppedValue, *value) - if stack.sp != 0 { - t.Errorf("Expected stack pointer to be 0 after pop, got %d", stack.sp) - } + require.Zero(t, stack.sp, "Expected stack pointer to be 0 after pop.") } // TestUnderflow tests the underflow condition when popping from an empty stack. @@ -38,9 +33,8 @@ func TestOptimizedStackUnderflow(t *testing.T) { var stack OptimizedStack _, err := stack.pop() - if err == nil { - t.Errorf("Expected an underflow error when popping from an empty stack, got nil") - } + + require.Error(t, err, "Expected an underflow error when popping from an empty stack, got nil") } // TestTop tests the top function without modifying the stack. @@ -53,17 +47,11 @@ func TestOptimizedStackTop(t *testing.T) { topValue, err := stack.top() - if err != nil { - t.Errorf("Expected no error, got %v", err) - } + require.NoError(t, err) - if *topValue != *value { - t.Errorf("Expected top value to be %v, got %v", value, *topValue) - } + require.Equal(t, *topValue, *value) - if stack.sp != 1 { - t.Errorf("Expected stack pointer to remain 1 after top, got %d", stack.sp) - } + require.Equal(t, stack.sp, 1, "Expected stack pointer to remain 1 after top.") } // TestReset tests the reset function to ensure it clears the stack. @@ -73,9 +61,8 @@ func TestOptimizedStackReset(t *testing.T) { stack.push(*uint256.NewInt(0)) stack.reset() - if stack.sp != 0 || len(stack.data) != 0 { - t.Errorf("Expected stack to be empty after reset, got sp: %d, len(data): %d", stack.sp, len(stack.data)) - } + require.Zero(t, stack.sp, "Expected stack to be empty after reset") + require.Zero(t, len(stack.data), "Expected stack to be empty after reset") } // TestPeekAt tests the peekAt function for retrieving elements without modifying the stack. @@ -90,14 +77,9 @@ func TestOptimizedStackPeekAt(t *testing.T) { peekedValue := stack.peekAt(2) - if peekedValue != *value1 { - t.Errorf("Expected to peek at value %v, got %v", value1, peekedValue) - } + require.Equal(t, peekedValue, *value1) - // Verify stack state hasn't changed after peekAt - if stack.sp != 2 { - t.Errorf("Expected stack pointer to remain 2 after peekAt, got %d", stack.sp) - } + require.Equal(t, stack.sp, 2) } // TestSwap tests the swap function to ensure it correctly swaps elements in the stack. @@ -115,7 +97,6 @@ func TestOptimizedStackSwap(t *testing.T) { stack.swap(1) // Verify swap operation - if stack.data[stack.sp-1] != *value1 || stack.data[stack.sp-2] != *value2 { - t.Errorf("Expected top two values to be swapped to %v and %v, got %v and %v", value1, value2, stack.data[stack.sp-1], stack.data[stack.sp-2]) - } + require.Equal(t, stack.data[stack.sp-1], *value1) + require.Equal(t, stack.data[stack.sp-2], *value2) } diff --git a/state/runtime/evm/state.go b/state/runtime/evm/state.go index 24deaaa22e..0668f75956 100644 --- a/state/runtime/evm/state.go +++ b/state/runtime/evm/state.go @@ -133,7 +133,6 @@ func (c *state) stackAtLeast(n int) bool { func (c *state) popHash() types.Hash { v := c.pop() - v.Bytes() return types.BytesToHash(v.Bytes()) } @@ -199,7 +198,6 @@ func (c *state) Run() ([]byte, error) { ) tracer := c.host.GetTracer() - iterationCount := 0 for !c.stop { op, ok = c.CurrentOpCode() @@ -253,7 +251,6 @@ func (c *state) Run() ([]byte, error) { } c.ip++ - iterationCount++ } if err := c.err; err != nil { @@ -282,7 +279,6 @@ func (c *state) Len() int { // allocateMemory allocates memory to enable accessing in the range of [offset, offset+size] // throws error if the given offset and size are negative // consumes gas if memory needs to be expanded -// func (c *state) allocateMemory(offset, size *big.Int) bool { func (c *state) allocateMemory(offset, size uint256.Int) bool { if !offset.IsUint64() || !size.IsUint64() { c.exit(errReturnDataOutOfBounds) From 9fe63c8842556c78643c627f0b99065a8e8ae5ff Mon Sep 17 00:00:00 2001 From: Mita Date: Tue, 19 Mar 2024 23:43:27 +0100 Subject: [PATCH 05/13] opMStore is changed to use newly introduced WriteToSlice() function with unrolled loop. This allows CPU to execute multiple instructions in parallel providing >200% increased speed compared to uint256.WriteToSlice() implementation. If needed, can be additionally implemented for different array lengths. --- state/runtime/evm/instructions.go | 53 ++++++++++++++- .../evm/instructions_benchmark_test.go | 67 +++++++++++++++++++ 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 9a934eb2e4..4759d28439 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -70,6 +70,53 @@ func (c *state) calculateGasForEIP2929(addr types.Address) uint64 { return gas } +// Generic WriteToSlice function that calls optimized function when +// applicable or generic one. +func WriteToSlice(z uint256.Int, dest []byte) { + if len(dest) == 32 { + WriteToSlice32(z, dest) + } else { + z.WriteToSlice(dest) + } +} + +// Optimized write to slice when destination size is 32 bytes. This way +// the CPU does not execute code in loop achieving greater paralelization +func WriteToSlice32(z uint256.Int, dest []byte) { + dest[31] = byte(z[0] >> uint64(8*0)) + dest[30] = byte(z[0] >> uint64(8*1)) + dest[29] = byte(z[0] >> uint64(8*2)) + dest[28] = byte(z[0] >> uint64(8*3)) + dest[27] = byte(z[0] >> uint64(8*4)) + dest[26] = byte(z[0] >> uint64(8*5)) + dest[25] = byte(z[0] >> uint64(8*6)) + dest[24] = byte(z[0] >> uint64(8*7)) + dest[23] = byte(z[1] >> uint64(8*0)) + dest[22] = byte(z[1] >> uint64(8*1)) + dest[21] = byte(z[1] >> uint64(8*2)) + dest[20] = byte(z[1] >> uint64(8*3)) + dest[19] = byte(z[1] >> uint64(8*4)) + dest[18] = byte(z[1] >> uint64(8*5)) + dest[17] = byte(z[1] >> uint64(8*6)) + dest[16] = byte(z[1] >> uint64(8*7)) + dest[15] = byte(z[2] >> uint64(8*0)) + dest[14] = byte(z[2] >> uint64(8*1)) + dest[13] = byte(z[2] >> uint64(8*2)) + dest[12] = byte(z[2] >> uint64(8*3)) + dest[11] = byte(z[2] >> uint64(8*4)) + dest[10] = byte(z[2] >> uint64(8*5)) + dest[9] = byte(z[2] >> uint64(8*6)) + dest[8] = byte(z[2] >> uint64(8*7)) + dest[7] = byte(z[3] >> uint64(8*0)) + dest[6] = byte(z[3] >> uint64(8*1)) + dest[5] = byte(z[3] >> uint64(8*2)) + dest[4] = byte(z[3] >> uint64(8*3)) + dest[3] = byte(z[3] >> uint64(8*4)) + dest[2] = byte(z[3] >> uint64(8*5)) + dest[1] = byte(z[3] >> uint64(8*6)) + dest[0] = byte(z[3] >> uint64(8*7)) +} + func opAdd(c *state) { a := c.pop() b := c.top() @@ -151,7 +198,7 @@ func opMulMod(c *state) { b := c.pop() z := c.top() - z = z.MulMod(&a, &b, z) + z.MulMod(&a, &b, z) } func opAnd(c *state) { @@ -179,7 +226,7 @@ func opByte(c *state) { x := c.pop() y := c.top() - y = y.Byte(&x) + y.Byte(&x) } func opNot(c *state) { @@ -340,7 +387,7 @@ func opMStore(c *state) { o := offset.Uint64() - val.WriteToSlice(c.memory[o : o+32]) + WriteToSlice(val, c.memory[o:o+32]) } func opMStore8(c *state) { diff --git a/state/runtime/evm/instructions_benchmark_test.go b/state/runtime/evm/instructions_benchmark_test.go index 115a3bff80..c378c4b8e0 100644 --- a/state/runtime/evm/instructions_benchmark_test.go +++ b/state/runtime/evm/instructions_benchmark_test.go @@ -1,10 +1,12 @@ package evm import ( + "math/big" "testing" "github.com/0xPolygon/polygon-edge/chain" "github.com/holiman/uint256" + "github.com/stretchr/testify/assert" ) type ( @@ -231,3 +233,68 @@ func BenchmarkInstruction_opSgt(b *testing.B) { operationBenchmark(b, s, opSgt, *op1, *op2) } + +func GetLarge256bitUint() uint256.Int { + hexStr := "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" + + bigInt := new(big.Int) + bigInt.SetString(hexStr, 16) + + return *uint256.MustFromBig(bigInt) +} + +func TestGenericWriteToSlice32(t *testing.T) { + + expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} + + var destination [32]byte + + value := GetLarge256bitUint() + + WriteToSlice32(value, destination[:]) + + assert.Equal(t, expectedDestinationSlice, destination) +} + +func TestGenericWriteToSlice(t *testing.T) { + + expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} + + var destination [32]byte + + value := GetLarge256bitUint() + + WriteToSlice(value, destination[:]) + + assert.Equal(t, expectedDestinationSlice, destination) +} + +func BenchmarkUint256WriteToSlice(b *testing.B) { + value := GetLarge256bitUint() + var destination [32]byte + + b.ResetTimer() + for i := 0; i < b.N; i++ { + value.WriteToSlice(destination[:]) + } +} + +func BenchmarkStaticUnrolledWriteToSlice(b *testing.B) { + value := GetLarge256bitUint() + var destination [32]byte + + b.ResetTimer() + for i := 0; i < b.N; i++ { + WriteToSlice32(value, destination[:]) + } +} + +func BenchmarkGenericStaticUnrolledWriteToSlice(b *testing.B) { + value := GetLarge256bitUint() + var destination [32]byte + + b.ResetTimer() + for i := 0; i < b.N; i++ { + WriteToSlice(value, destination[:]) + } +} From 389282a1715e5a22d00f4494e0169506b8ea3f9a Mon Sep 17 00:00:00 2001 From: Mita Date: Tue, 19 Mar 2024 23:54:16 +0100 Subject: [PATCH 06/13] Fixing linter errors. --- state/runtime/evm/instructions_benchmark_test.go | 8 ++++++-- state/runtime/evm/optimized_stack.go | 3 --- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/state/runtime/evm/instructions_benchmark_test.go b/state/runtime/evm/instructions_benchmark_test.go index c378c4b8e0..f5ffbc9d16 100644 --- a/state/runtime/evm/instructions_benchmark_test.go +++ b/state/runtime/evm/instructions_benchmark_test.go @@ -244,7 +244,6 @@ func GetLarge256bitUint() uint256.Int { } func TestGenericWriteToSlice32(t *testing.T) { - expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} var destination [32]byte @@ -257,7 +256,6 @@ func TestGenericWriteToSlice32(t *testing.T) { } func TestGenericWriteToSlice(t *testing.T) { - expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} var destination [32]byte @@ -271,9 +269,11 @@ func TestGenericWriteToSlice(t *testing.T) { func BenchmarkUint256WriteToSlice(b *testing.B) { value := GetLarge256bitUint() + var destination [32]byte b.ResetTimer() + for i := 0; i < b.N; i++ { value.WriteToSlice(destination[:]) } @@ -281,9 +281,11 @@ func BenchmarkUint256WriteToSlice(b *testing.B) { func BenchmarkStaticUnrolledWriteToSlice(b *testing.B) { value := GetLarge256bitUint() + var destination [32]byte b.ResetTimer() + for i := 0; i < b.N; i++ { WriteToSlice32(value, destination[:]) } @@ -291,9 +293,11 @@ func BenchmarkStaticUnrolledWriteToSlice(b *testing.B) { func BenchmarkGenericStaticUnrolledWriteToSlice(b *testing.B) { value := GetLarge256bitUint() + var destination [32]byte b.ResetTimer() + for i := 0; i < b.N; i++ { WriteToSlice(value, destination[:]) } diff --git a/state/runtime/evm/optimized_stack.go b/state/runtime/evm/optimized_stack.go index 1a9933df73..99f87a633d 100644 --- a/state/runtime/evm/optimized_stack.go +++ b/state/runtime/evm/optimized_stack.go @@ -10,7 +10,6 @@ import ( // to keep track of the current stack pointer. // OptimizedStack uint256 integers for improved operations on values on the // stack and minimizes heap allocations. -// TODO: Check if sp field can be removed. type OptimizedStack struct { sp int // Stack pointer to track the top of the stack data []uint256.Int // Slice to store the stack's elements @@ -61,14 +60,12 @@ func (s *OptimizedStack) top() (*uint256.Int, error) { // peekAt returns the element at the nth position from the top of the stack, // without modifying the stack. It does not perform bounds checking and it // returns the value of the element, not the reference. -// TODO: Check on error handling func (s *OptimizedStack) peekAt(n int) uint256.Int { return s.data[s.sp-n] } // swap exchanges the top element of the stack with the element at the n-th position // from the top. It does not perform bounds checking and assumes valid input. -// TODO: Check on error handling func (s *OptimizedStack) swap(n int) { s.data[s.sp-1], s.data[s.sp-n-1] = s.data[s.sp-n-1], s.data[s.sp-1] } From 17652eed4a6d8a3b348477a94ea3b6e65cd98b80 Mon Sep 17 00:00:00 2001 From: Mita Date: Wed, 20 Mar 2024 20:11:29 +0100 Subject: [PATCH 07/13] setBytes to use uint256 instead of big.int. --- state/runtime/evm/instructions.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 4759d28439..8dd97ad899 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -621,7 +621,7 @@ func opCallDataLoad(c *state) { bufPtr := bufPool.Get().(*[]byte) buf := *bufPtr - c.setBytes(buf[:32], c.msg.Input, 32, offset.ToBig()) + c.setBytes(buf[:32], c.msg.Input, 32, *offset) offset.SetBytes(buf[:32]) bufPool.Put(bufPtr) } @@ -713,7 +713,7 @@ func opGas(c *state) { c.push(*uint256.NewInt(c.gas)) } -func (c *state) setBytes(dst, input []byte, size uint64, dataOffset *big.Int) { +func (c *state) setBytes(dst, input []byte, size uint64, dataOffset uint256.Int) { if !dataOffset.IsUint64() { // overflow, copy 'size' 0 bytes to dst for i := uint64(0); i < size; i++ { @@ -771,7 +771,7 @@ func opExtCodeCopy(c *state) { code := c.host.GetCode(address) if size != 0 { - c.setBytes(c.memory[memOffset.Uint64():], code, size, codeOffset.ToBig()) + c.setBytes(c.memory[memOffset.Uint64():], code, size, codeOffset) } } @@ -790,7 +790,7 @@ func opCallDataCopy(c *state) { } if size != 0 { - c.setBytes(c.memory[memOffset.Uint64():], c.msg.Input, size, dataOffset.ToBig()) + c.setBytes(c.memory[memOffset.Uint64():], c.msg.Input, size, dataOffset) } } @@ -861,7 +861,7 @@ func opCodeCopy(c *state) { } if size != 0 { - c.setBytes(c.memory[memOffset.Uint64():], c.code, size, dataOffset.ToBig()) + c.setBytes(c.memory[memOffset.Uint64():], c.code, size, dataOffset) } } From 8cd60f220cf2fe180297a6b53591c98c67db7adc Mon Sep 17 00:00:00 2001 From: Mita Date: Wed, 20 Mar 2024 21:16:39 +0100 Subject: [PATCH 08/13] Fixing linter errors. --- state/runtime/evm/instructions_test.go | 10 +++++----- state/runtime/evm/optimized_stack.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/state/runtime/evm/instructions_test.go b/state/runtime/evm/instructions_test.go index e573f56570..0a727c60bb 100644 --- a/state/runtime/evm/instructions_test.go +++ b/state/runtime/evm/instructions_test.go @@ -568,8 +568,8 @@ func TestMStore8(t *testing.T) { s, closeFn := getState(&chain.ForksInTime{}) defer closeFn() - s.push(one256) //value - s.push(*offsetStore) //offset + s.push(one256) // value + s.push(*offsetStore) // offset opMStore8(s) @@ -1171,9 +1171,9 @@ func TestCodeCopyLenZero(t *testing.T) { var expectedGas = s.gas - s.push(zero256) //length - s.push(zero256) //dataOffset - s.push(zero256) //memOffset + s.push(zero256) // length + s.push(zero256) // dataOffset + s.push(zero256) // memOffset opCodeCopy(s) diff --git a/state/runtime/evm/optimized_stack.go b/state/runtime/evm/optimized_stack.go index 99f87a633d..f31e6aee9c 100644 --- a/state/runtime/evm/optimized_stack.go +++ b/state/runtime/evm/optimized_stack.go @@ -34,7 +34,7 @@ func (s *OptimizedStack) push(val uint256.Int) { func (s *OptimizedStack) pop() (uint256.Int, error) { if s.sp == 0 { // The stack is empty, return a zero value and an underflow error - return *new(uint256.Int), &runtime.StackUnderflowError{} + return *uint256.NewInt(0), &runtime.StackUnderflowError{} } o := s.data[s.sp-1] // Get the top element From fd2f4a224783626322edfdeb3f40c840f732083c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Thu, 28 Mar 2024 10:38:40 +0100 Subject: [PATCH 09/13] Go mod tidy --- go.mod | 6 ++++-- go.sum | 30 +++++++++++++++++------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index bd344647aa..2cfbac6f91 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/0xPolygon/polygon-edge -go 1.20 +go 1.21 + +toolchain go1.21.6 require ( cloud.google.com/go/secretmanager v1.11.5 @@ -53,7 +55,7 @@ require ( pgregory.net/rapid v1.1.0 ) -require github.com/holiman/uint256 v1.2.4 // indirect +require github.com/holiman/uint256 v1.2.4 require ( cloud.google.com/go/compute v1.23.3 // indirect diff --git a/go.sum b/go.sum index ca69053bdd..cd50ffa015 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= @@ -92,11 +93,9 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -106,10 +105,10 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -128,6 +127,7 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= @@ -174,6 +174,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -183,7 +184,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -194,6 +194,7 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-toolsmith/astcopy v1.0.2 h1:YnWf5Rnh1hUudj11kei53kI57quN/VH6Hp1n+erozn0= github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= @@ -246,6 +247,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -275,6 +277,7 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -306,6 +309,7 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -344,7 +348,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -352,7 +355,6 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -368,11 +370,14 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= @@ -388,6 +393,7 @@ github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEH github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA= github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= @@ -435,7 +441,6 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -475,7 +480,6 @@ github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -496,6 +500,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= @@ -505,7 +510,6 @@ github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= @@ -572,6 +576,7 @@ github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Id github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -580,7 +585,6 @@ github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAjPbcMsODrTQUpJ02eNLUoxBg= github.com/secure-systems-lab/go-securesystemslib v0.7.0/go.mod h1:/2gYnlnHVQ6xeGtfIqFy7Do03K4cdCY0A/GlJLDKLHI= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -641,7 +645,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -667,8 +670,6 @@ github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4x github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -687,6 +688,7 @@ go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZV go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -700,6 +702,7 @@ go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -981,6 +984,7 @@ gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/gotraceui v0.2.0 h1:dmNsfQ9Vl3GwbiVD7Z8d/osC6WtGGrasyrC2suc4ZIQ= +honnef.co/go/gotraceui v0.2.0/go.mod h1:qHo4/W75cA3bX0QQoSvDjbJa4R8mAyyFjbWAj63XElc= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 127e30cf77088889b3efccbc22fa1856f5d1bb7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Thu, 28 Mar 2024 10:44:00 +0100 Subject: [PATCH 10/13] Lint fix --- e2e-polybft/e2e/jsonrpc_test.go | 2 +- e2e-polybft/e2e/storage_test.go | 2 +- e2e-polybft/e2e/txpool_test.go | 4 ++-- state/runtime/evm/instructions.go | 1 - .../evm/instructions_benchmark_test.go | 20 ++++++++++--------- state/runtime/evm/instructions_test.go | 8 ++++---- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index ff46c54622..c248142399 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -226,7 +226,7 @@ func TestE2E_JsonRPC(t *testing.T) { require.NoError(t, err) resp, err := newEthClient.Call(&bladeRPC.CallMsg{ - From: types.Address(acctZeroBalance.Address()), + From: acctZeroBalance.Address(), To: &target, Data: input, }, bladeRPC.LatestBlockNumber, nil) diff --git a/e2e-polybft/e2e/storage_test.go b/e2e-polybft/e2e/storage_test.go index b9ff7424c9..d6199fed0c 100644 --- a/e2e-polybft/e2e/storage_test.go +++ b/e2e-polybft/e2e/storage_test.go @@ -66,7 +66,7 @@ func TestE2E_Storage(t *testing.T) { } txn.SetFrom(sender.Address()) - txn.SetTo((*types.Address)(&to)) + txn.SetTo(&to) txn.SetGas(21000) txn.SetValue(big.NewInt(int64(i))) txn.SetNonce(uint64(i)) diff --git a/e2e-polybft/e2e/txpool_test.go b/e2e-polybft/e2e/txpool_test.go index c1d007cd91..cac5a9e991 100644 --- a/e2e-polybft/e2e/txpool_test.go +++ b/e2e-polybft/e2e/txpool_test.go @@ -59,7 +59,7 @@ func TestE2E_TxPool_Transfer(t *testing.T) { if i%2 == 0 { txData = types.NewDynamicFeeTx( types.WithFrom(sender.Address()), - types.WithTo((*types.Address)(&to)), + types.WithTo(&to), types.WithGas(30000), // enough to send a transfer types.WithValue(big.NewInt(int64(sendAmount))), types.WithNonce(uint64(i)), @@ -69,7 +69,7 @@ func TestE2E_TxPool_Transfer(t *testing.T) { } else { txData = types.NewLegacyTx( types.WithFrom(sender.Address()), - types.WithTo((*types.Address)(&to)), + types.WithTo(&to), types.WithGas(30000), types.WithValue(big.NewInt(int64(sendAmount))), types.WithNonce(uint64(i)), diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 4369cab9cd..8dd97ad899 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -1297,7 +1297,6 @@ func (c *state) buildCallContract(op OpCode) (*runtime.Contract, uint64, uint64, return nil, 0, 0, nil } - gas = initialGas.Uint64() } diff --git a/state/runtime/evm/instructions_benchmark_test.go b/state/runtime/evm/instructions_benchmark_test.go index f5ffbc9d16..d788e2ef10 100644 --- a/state/runtime/evm/instructions_benchmark_test.go +++ b/state/runtime/evm/instructions_benchmark_test.go @@ -32,13 +32,15 @@ func BenchmarkStack(b *testing.B) { b.StopTimer() } -func operationBenchmark(b *testing.B, s *state, op instructionOperation, op1 uint256.Int, op2 uint256.Int) { +func operationBenchmark(b *testing.B, s *state, op instructionOperation, operands ...uint256.Int) { b.Helper() b.ResetTimer() for i := 0; i < b.N; i++ { - s.push(op1) - s.push(op2) + for _, op := range operands { + s.push(op) + } + op(s) s.pop() } @@ -234,7 +236,7 @@ func BenchmarkInstruction_opSgt(b *testing.B) { operationBenchmark(b, s, opSgt, *op1, *op2) } -func GetLarge256bitUint() uint256.Int { +func getLarge256bitUint() uint256.Int { hexStr := "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" bigInt := new(big.Int) @@ -248,7 +250,7 @@ func TestGenericWriteToSlice32(t *testing.T) { var destination [32]byte - value := GetLarge256bitUint() + value := getLarge256bitUint() WriteToSlice32(value, destination[:]) @@ -260,7 +262,7 @@ func TestGenericWriteToSlice(t *testing.T) { var destination [32]byte - value := GetLarge256bitUint() + value := getLarge256bitUint() WriteToSlice(value, destination[:]) @@ -268,7 +270,7 @@ func TestGenericWriteToSlice(t *testing.T) { } func BenchmarkUint256WriteToSlice(b *testing.B) { - value := GetLarge256bitUint() + value := getLarge256bitUint() var destination [32]byte @@ -280,7 +282,7 @@ func BenchmarkUint256WriteToSlice(b *testing.B) { } func BenchmarkStaticUnrolledWriteToSlice(b *testing.B) { - value := GetLarge256bitUint() + value := getLarge256bitUint() var destination [32]byte @@ -292,7 +294,7 @@ func BenchmarkStaticUnrolledWriteToSlice(b *testing.B) { } func BenchmarkGenericStaticUnrolledWriteToSlice(b *testing.B) { - value := GetLarge256bitUint() + value := getLarge256bitUint() var destination [32]byte diff --git a/state/runtime/evm/instructions_test.go b/state/runtime/evm/instructions_test.go index bd2963dee4..8173610925 100644 --- a/state/runtime/evm/instructions_test.go +++ b/state/runtime/evm/instructions_test.go @@ -1191,9 +1191,9 @@ func TestCodeCopy(t *testing.T) { s, cancelFn := getState(&chain.ForksInTime{}) defer cancelFn() - s.push(one256) //length - s.push(zero256) //dataOffset - s.push(*uint256.NewInt(31)) //memOffset + s.push(one256) // length + s.push(zero256) // dataOffset + s.push(*uint256.NewInt(31)) // memOffset s.code = one.Bytes() @@ -1682,7 +1682,7 @@ func Test_opSload(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - //t.Parallel() + // t.Parallel() s, closeFn := getState(tt.config) defer closeFn() From 6a70e939d34b70e1099e8ebbedfd959ec23a7eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Thu, 28 Mar 2024 10:45:40 +0100 Subject: [PATCH 11/13] Revert go version --- go.mod | 4 +--- go.sum | 17 ----------------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 2cfbac6f91..b8ad524965 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/0xPolygon/polygon-edge -go 1.21 - -toolchain go1.21.6 +go 1.20 require ( cloud.google.com/go/secretmanager v1.11.5 diff --git a/go.sum b/go.sum index cd50ffa015..3655c11e1a 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= @@ -105,7 +104,6 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= @@ -127,7 +125,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= @@ -174,7 +171,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -194,7 +190,6 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= -github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-toolsmith/astcopy v1.0.2 h1:YnWf5Rnh1hUudj11kei53kI57quN/VH6Hp1n+erozn0= github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= @@ -247,7 +242,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -277,7 +271,6 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= -github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -309,7 +302,6 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= -github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -370,14 +362,11 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= @@ -393,7 +382,6 @@ github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEH github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA= github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= @@ -500,7 +488,6 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= @@ -576,7 +563,6 @@ github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Id github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -688,7 +674,6 @@ go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZV go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -702,7 +687,6 @@ go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -984,7 +968,6 @@ gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/gotraceui v0.2.0 h1:dmNsfQ9Vl3GwbiVD7Z8d/osC6WtGGrasyrC2suc4ZIQ= -honnef.co/go/gotraceui v0.2.0/go.mod h1:qHo4/W75cA3bX0QQoSvDjbJa4R8mAyyFjbWAj63XElc= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 8ee88f099134ce23e0659c9d860a6a2ccb87db70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Thu, 28 Mar 2024 11:23:54 +0100 Subject: [PATCH 12/13] Address comments --- state/runtime/evm/instructions.go | 5 +- .../evm/instructions_benchmark_test.go | 25 ------ state/runtime/evm/instructions_test.go | 82 ++++++++++++------- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 8dd97ad899..a6fe6de640 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -409,10 +409,11 @@ func opSload(c *state) { var gas uint64 if c.config.Berlin { - if _, slotPresent := c.host.ContainsAccessListSlot(c.msg.Address, uint256ToHash(loc)); !slotPresent { + storageKey := uint256ToHash(loc) + if _, slotPresent := c.host.ContainsAccessListSlot(c.msg.Address, storageKey); !slotPresent { gas = ColdStorageReadCostEIP2929 - c.host.AddSlotToAccessList(c.msg.Address, uint256ToHash(loc)) + c.host.AddSlotToAccessList(c.msg.Address, storageKey) } else { gas = WarmStorageReadCostEIP2929 } diff --git a/state/runtime/evm/instructions_benchmark_test.go b/state/runtime/evm/instructions_benchmark_test.go index d788e2ef10..d0bbf29fbb 100644 --- a/state/runtime/evm/instructions_benchmark_test.go +++ b/state/runtime/evm/instructions_benchmark_test.go @@ -6,7 +6,6 @@ import ( "github.com/0xPolygon/polygon-edge/chain" "github.com/holiman/uint256" - "github.com/stretchr/testify/assert" ) type ( @@ -245,30 +244,6 @@ func getLarge256bitUint() uint256.Int { return *uint256.MustFromBig(bigInt) } -func TestGenericWriteToSlice32(t *testing.T) { - expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} - - var destination [32]byte - - value := getLarge256bitUint() - - WriteToSlice32(value, destination[:]) - - assert.Equal(t, expectedDestinationSlice, destination) -} - -func TestGenericWriteToSlice(t *testing.T) { - expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} - - var destination [32]byte - - value := getLarge256bitUint() - - WriteToSlice(value, destination[:]) - - assert.Equal(t, expectedDestinationSlice, destination) -} - func BenchmarkUint256WriteToSlice(b *testing.B) { value := getLarge256bitUint() diff --git a/state/runtime/evm/instructions_test.go b/state/runtime/evm/instructions_test.go index 8173610925..740dcee72e 100644 --- a/state/runtime/evm/instructions_test.go +++ b/state/runtime/evm/instructions_test.go @@ -2211,39 +2211,11 @@ func Test_opReturnDataCopy(t *testing.T) { opReturnDataCopy(state) - assert.True(t, CompareStates(test.resultState, state)) + assert.True(t, compareStates(test.resultState, state)) }) } } -// Since the state is complex structure, here is the specialized comparison -// function that checks significant fields. This function should be updated -// to suite future needs. -func CompareStates(a *state, b *state) bool { - // Compare simple fields - if a.ip != b.ip || a.lastGasCost != b.lastGasCost || a.stack.sp != b.stack.sp || !errors.Is(a.err, b.err) || a.stop != b.stop || a.gas != b.gas { - return false - } - - // Deep compare slices - if !reflect.DeepEqual(a.code, b.code) || !reflect.DeepEqual(a.tmp, b.tmp) || !reflect.DeepEqual(a.returnData, b.returnData) || !reflect.DeepEqual(a.memory, b.memory) { - return false - } - - // Deep comparison of stacks - if len(a.stack.data) != len(b.stack.data) { - return false - } - - for i := range a.stack.data { - if a.stack.data[i] != b.stack.data[i] { - return false - } - } - - return true -} - func Test_opCall(t *testing.T) { t.Parallel() @@ -2319,3 +2291,55 @@ func Test_opCall(t *testing.T) { }) } } + +func TestGenericWriteToSlice32(t *testing.T) { + expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} + + var destination [32]byte + + value := getLarge256bitUint() + + WriteToSlice32(value, destination[:]) + + assert.Equal(t, expectedDestinationSlice, destination) +} + +func TestGenericWriteToSlice(t *testing.T) { + expectedDestinationSlice := [32]uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} + + var destination [32]byte + + value := getLarge256bitUint() + + WriteToSlice(value, destination[:]) + + assert.Equal(t, expectedDestinationSlice, destination) +} + +// Since the state is complex structure, here is the specialized comparison +// function that checks significant fields. This function should be updated +// to suite future needs. +func compareStates(a *state, b *state) bool { + // Compare simple fields + if a.ip != b.ip || a.lastGasCost != b.lastGasCost || a.stack.sp != b.stack.sp || !errors.Is(a.err, b.err) || a.stop != b.stop || a.gas != b.gas { + return false + } + + // Deep compare slices + if !reflect.DeepEqual(a.code, b.code) || !reflect.DeepEqual(a.tmp, b.tmp) || !reflect.DeepEqual(a.returnData, b.returnData) || !reflect.DeepEqual(a.memory, b.memory) { + return false + } + + // Deep comparison of stacks + if len(a.stack.data) != len(b.stack.data) { + return false + } + + for i := range a.stack.data { + if a.stack.data[i] != b.stack.data[i] { + return false + } + } + + return true +} From 32f26ad4cb82732b704c366a906d2079093573ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= Date: Thu, 28 Mar 2024 11:51:03 +0100 Subject: [PATCH 13/13] Remove pointer dereferencing and use value type reference --- state/runtime/evm/instructions.go | 42 +++++++++++------------ state/runtime/evm/optimized_stack.go | 2 +- state/runtime/evm/optimized_stack_test.go | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index a6fe6de640..534ae42f6e 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -527,9 +527,9 @@ func opSha3(c *state) { c.tmp = keccak.Keccak256(c.tmp[:0], c.tmp) - v := uint256.NewInt(0) + v := uint256.Int{0} v.SetBytes(c.tmp) - c.push(*v) + c.push(v) } func opPop(c *state) { @@ -539,9 +539,9 @@ func opPop(c *state) { // context operations func opAddress(c *state) { - v := uint256.NewInt(0) + v := uint256.Int{0} v.SetBytes(c.msg.Address.Bytes()) - c.push(*v) + c.push(v) } func opBalance(c *state) { @@ -595,17 +595,17 @@ func opChainID(c *state) { } func opOrigin(c *state) { - x := uint256.NewInt(0) + x := uint256.Int{0} x.SetBytes(c.host.GetTxContext().Origin.Bytes()) - c.push(*x) + c.push(x) } func opCaller(c *state) { - x := uint256.NewInt(0) + x := uint256.Int{0} x.SetBytes(c.msg.Caller.Bytes()) - c.push(*x) + c.push(x) } func opCallValue(c *state) { @@ -613,7 +613,7 @@ func opCallValue(c *state) { uintValue, _ := uint256.FromBig(value) c.push(*uintValue) } else { - c.push(*uint256.NewInt(0)) + c.push(uint256.Int{0}) } } @@ -658,9 +658,9 @@ func opExtCodeSize(c *state) { } func opGasPrice(c *state) { - x := uint256.NewInt(0) + x := uint256.Int{0} x.SetBytes(c.host.GetTxContext().GasPrice.Bytes()) - c.push(*x) + c.push(x) } func opReturnDataSize(c *state) { @@ -694,12 +694,12 @@ func opExtCodeHash(c *state) { return } - v := uint256.NewInt(0) + v := uint256.Int{0} if !c.host.Empty(address) { v.SetBytes(c.host.GetCodeHash(address).Bytes()) } - c.push(*v) + c.push(v) } func opPC(c *state) { @@ -997,7 +997,7 @@ func opPush0(c *state) { return } - c.push(*uint256.NewInt(0)) + c.push(uint256.Int{0}) } func opPush(n int) instruction { @@ -1005,14 +1005,14 @@ func opPush(n int) instruction { ins := c.code ip := c.ip - d := uint256.NewInt(0) + d := uint256.Int{0} if ip+1+n > len(ins) { d.SetBytes(append(ins[ip+1:], make([]byte, n)...)) } else { d.SetBytes(ins[ip+1 : ip+1+n]) } - c.push(*d) + c.push(d) c.ip += n } @@ -1108,7 +1108,7 @@ func opCreate(op OpCode) instruction { contract, err := c.buildCreateContract(op) if err != nil { - c.push(*uint256.NewInt(0)) + c.push(uint256.Int{0}) if contract != nil { c.gas += contract.Gas @@ -1126,7 +1126,7 @@ func opCreate(op OpCode) instruction { // Correct call result := c.host.Callx(contract, c.host) - v := uint256.NewInt(0) + v := uint256.Int{0} if op == CREATE && c.config.Homestead && errors.Is(result.Err, runtime.ErrCodeStoreOutOfGas) { v.SetUint64(0) } else if op == CREATE && result.Failed() && !errors.Is(result.Err, runtime.ErrCodeStoreOutOfGas) { @@ -1137,7 +1137,7 @@ func opCreate(op OpCode) instruction { v.SetBytes(contract.Address.Bytes()) } - c.push(*v) + c.push(v) c.gas += result.GasLeft if result.Reverted() { @@ -1191,7 +1191,7 @@ func opCall(op OpCode) instruction { contract, offset, size, err := c.buildCallContract(op) if err != nil { - c.push(*uint256.NewInt(0)) + c.push(uint256.Int{0}) if contract != nil { c.gas += contract.Gas @@ -1211,7 +1211,7 @@ func opCall(op OpCode) instruction { if result.Succeeded() { c.push(*uint256.NewInt(1)) } else { - c.push(*uint256.NewInt(0)) + c.push(uint256.Int{0}) } if result.Succeeded() || result.Reverted() { diff --git a/state/runtime/evm/optimized_stack.go b/state/runtime/evm/optimized_stack.go index f31e6aee9c..8f54b6825d 100644 --- a/state/runtime/evm/optimized_stack.go +++ b/state/runtime/evm/optimized_stack.go @@ -34,7 +34,7 @@ func (s *OptimizedStack) push(val uint256.Int) { func (s *OptimizedStack) pop() (uint256.Int, error) { if s.sp == 0 { // The stack is empty, return a zero value and an underflow error - return *uint256.NewInt(0), &runtime.StackUnderflowError{} + return uint256.Int{0}, &runtime.StackUnderflowError{} } o := s.data[s.sp-1] // Get the top element diff --git a/state/runtime/evm/optimized_stack_test.go b/state/runtime/evm/optimized_stack_test.go index 0d6109606a..1c47d03fed 100644 --- a/state/runtime/evm/optimized_stack_test.go +++ b/state/runtime/evm/optimized_stack_test.go @@ -58,7 +58,7 @@ func TestOptimizedStackTop(t *testing.T) { func TestOptimizedStackReset(t *testing.T) { var stack OptimizedStack - stack.push(*uint256.NewInt(0)) + stack.push(uint256.Int{0}) stack.reset() require.Zero(t, stack.sp, "Expected stack to be empty after reset")