From c203d907017acc21aa53fa4b5d05f4cfa5cc1566 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Wed, 27 Aug 2025 15:18:35 +0200 Subject: [PATCH 1/8] fix: simulate and compute total gas usage before distribution --- go.mod | 45 ++++++++-- go.sum | 102 +++++++++++++++++++---- internal/distributor/distributor.go | 30 +------ internal/distributor/distributor_test.go | 11 ++- internal/pipeline.go | 32 +++---- internal/runtime/helper.go | 43 ++++++++++ internal/runtime/package_deployment.go | 78 ++++++++++------- internal/runtime/realm_call.go | 46 +++++++--- internal/runtime/realm_deployment.go | 77 ++++++++++------- internal/runtime/runtime.go | 10 +++ internal/runtime/runtime_test.go | 4 +- internal/runtime/source.go | 5 ++ 12 files changed, 339 insertions(+), 144 deletions(-) diff --git a/go.mod b/go.mod index d23248a..59381f6 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,11 @@ module github.com/gnolang/supernova -go 1.23 +go 1.23.0 + +toolchain go1.24.1 require ( - github.com/gnolang/gno v0.0.0-20250129165357-b392287f0d2c + github.com/gnolang/gno v0.0.0-20250826105341-fba926958b6b github.com/peterbourgon/ff/v3 v3.4.0 github.com/schollz/progressbar/v3 v3.18.0 github.com/stretchr/testify v1.10.0 @@ -11,30 +13,54 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.5 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/gofrs/flock v0.12.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/onsi/gomega v1.31.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.15.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/cors v1.11.1 // indirect github.com/rs/xid v1.6.0 // indirect github.com/sig-0/insertion-queue v0.0.0-20241004125609-6b3ca841346b // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect go.etcd.io/bbolt v1.3.11 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect @@ -46,14 +72,15 @@ require ( go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.32.0 // indirect + golang.org/x/crypto v0.40.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/net v0.34.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/term v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.34.0 // indirect + golang.org/x/term v0.33.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.35.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/grpc v1.69.4 // indirect diff --git a/go.sum b/go.sum index 447c34a..60f31ad 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= @@ -30,12 +34,29 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= +github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -53,14 +74,23 @@ 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 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/gnolang/gno v0.0.0-20250129165357-b392287f0d2c h1:9XalLZCqb6vfNUXojzVj4WXgpQEAONsyeoAH+DTbT1E= -github.com/gnolang/gno v0.0.0-20250129165357-b392287f0d2c/go.mod h1:9UN8hxUrbTQzq5oqXdx39seAtRBhUyONGw0voV4lMBs= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/gnolang/gno v0.0.0-20250826105341-fba926958b6b h1:z0iw3ObgSnibeOpORPzRZjnx6v5eeSbQ35zgdoZndjE= +github.com/gnolang/gno v0.0.0-20250826105341-fba926958b6b/go.mod h1:j9wKq29meqwktEj2ReqPbSkeYUwoisfxHHVeV20lhtw= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -89,7 +119,11 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +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= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -100,6 +134,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -120,12 +156,24 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= +github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= @@ -147,6 +195,10 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= @@ -175,23 +227,33 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -201,17 +263,25 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= diff --git a/internal/distributor/distributor.go b/internal/distributor/distributor.go index d42de88..cc4bfbb 100644 --- a/internal/distributor/distributor.go +++ b/internal/distributor/distributor.go @@ -42,41 +42,19 @@ func NewDistributor( func (d *Distributor) Distribute( distributor crypto.PrivKey, accounts []crypto.Address, - transactions uint64, chainID string, + calculatedRuntimeCost std.Coin, ) ([]std.Account, error) { fmt.Printf("\n💸 Starting Fund Distribution 💸\n\n") - // Calculate the base fees - subAccountCost := calculateRuntimeCosts(int64(transactions)) fmt.Printf( "Calculated sub-account cost as %d %s\n", - subAccountCost.Amount, - subAccountCost.Denom, + calculatedRuntimeCost.Amount, + calculatedRuntimeCost.Denom, ) // Fund the accounts - return d.fundAccounts(distributor, accounts, subAccountCost, chainID) -} - -// calculateRuntimeCosts calculates the amount of funds -// each account needs to have in order to participate in the -// stress test run -func calculateRuntimeCosts(totalTx int64) std.Coin { - // Cost of a single run transaction for the sub-account - // NOTE: Since there is no gas estimation support yet, this value - // is fixed, but it will change in the future once pricing estimations - // are added - baseTxCost := common.CalculateFeeInRatio(1_000_000, common.DefaultGasPrice) - - // Each account should have enough funds - // to execute the entire run - subAccountCost := std.Coin{ - Denom: common.Denomination, - Amount: totalTx * baseTxCost.GasFee.Amount, - } - - return subAccountCost + return d.fundAccounts(distributor, accounts, calculatedRuntimeCost, chainID) } // fundAccounts attempts to fund accounts that have missing funds, diff --git a/internal/distributor/distributor_test.go b/internal/distributor/distributor_test.go index 33ce5f4..3454128 100644 --- a/internal/distributor/distributor_test.go +++ b/internal/distributor/distributor_test.go @@ -17,7 +17,10 @@ func TestDistributor_Distribute(t *testing.T) { var ( numTx = uint64(1000) - singleCost = calculateRuntimeCosts(int64(numTx)) + singleCost = std.Coin{ + Denom: common.Denomination, + Amount: int64(numTx) * 100_00, + } ) getAccount := func(address string, accounts []crypto.PrivKey) crypto.PrivKey { @@ -66,7 +69,7 @@ func TestDistributor_Distribute(t *testing.T) { addresses = append(addresses, account.PubKey().Address()) } - readyAccounts, err := d.Distribute(accounts[0], addresses, numTx, "dummy") + readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", singleCost) if err != nil { t.Fatalf("unable to distribute funds, %v", err) } @@ -122,7 +125,7 @@ func TestDistributor_Distribute(t *testing.T) { addresses = append(addresses, account.PubKey().Address()) } - readyAccounts, err := d.Distribute(accounts[0], addresses, numTx, "dummy") + readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", singleCost) assert.Nil(t, readyAccounts) assert.ErrorIs(t, err, errInsufficientFunds) @@ -192,7 +195,7 @@ func TestDistributor_Distribute(t *testing.T) { addresses = append(addresses, account.PubKey().Address()) } - readyAccounts, err := d.Distribute(accounts[0], addresses, numTx, "dummy") + readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", singleCost) if err != nil { t.Fatalf("unable to distribute funds, %v", err) } diff --git a/internal/pipeline.go b/internal/pipeline.go index f76d047..f27fa54 100644 --- a/internal/pipeline.go +++ b/internal/pipeline.go @@ -6,6 +6,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/crypto/bip39" + "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/supernova/internal/batcher" "github.com/gnolang/supernova/internal/client" "github.com/gnolang/supernova/internal/collector" @@ -66,13 +67,15 @@ func (p *Pipeline) Execute() error { accounts := p.initializeAccounts() // Predeploy any pending transactions - if err := prepareRuntime( + estimatedGas, err := prepareRuntime( mode, accounts[0], p.cfg.ChainID, p.cli, txRuntime, - ); err != nil { + p.cfg.Transactions, + ) + if err != nil { return err } @@ -86,8 +89,8 @@ func (p *Pipeline) Execute() error { runAccounts, err := distributor.NewDistributor(p.cli).Distribute( accounts[0], addresses, - p.cfg.Transactions, p.cfg.ChainID, + estimatedGas, ) if err != nil { return fmt.Errorf("unable to distribute funds, %w", err) @@ -192,19 +195,20 @@ func prepareRuntime( chainID string, cli pipelineClient, txRuntime runtime.Runtime, -) error { - if mode != runtime.RealmCall { - return nil - } - - fmt.Printf("\n✨ Starting Predeployment Procedure ✨\n\n") - + transactions uint64, +) (std.Coin, error) { // Get the deployer account deployer, err := cli.GetAccount(deployerKey.PubKey().Address().String()) if err != nil { - return fmt.Errorf("unable to fetch deployer account, %w", err) + return std.Coin{}, fmt.Errorf("unable to fetch deployer account, %w", err) + } + + if mode != runtime.RealmCall { + return txRuntime.CalculateRuntimeCosts(deployer, deployerKey, chainID, cli.EstimateGas, transactions) } + fmt.Printf("\n✨ Starting Predeployment Procedure ✨\n\n") + // Get the predeploy transactions predeployTxs, err := txRuntime.Initialize( deployer, @@ -213,7 +217,7 @@ func prepareRuntime( cli.EstimateGas, ) if err != nil { - return fmt.Errorf("unable to initialize runtime, %w", err) + return std.Coin{}, fmt.Errorf("unable to initialize runtime, %w", err) } bar := progressbar.Default(int64(len(predeployTxs)), "predeployed txs") @@ -221,7 +225,7 @@ func prepareRuntime( // Execute the predeploy transactions for _, tx := range predeployTxs { if err := cli.BroadcastTransaction(tx); err != nil { - return fmt.Errorf("unable to broadcast predeploy tx, %w", err) + return std.Coin{}, fmt.Errorf("unable to broadcast predeploy tx, %w", err) } _ = bar.Add(1) //nolint:errcheck // No need to check @@ -229,5 +233,5 @@ func prepareRuntime( fmt.Printf("✅ Successfully predeployed %d transactions\n", len(predeployTxs)) - return nil + return txRuntime.CalculateRuntimeCosts(deployer, deployerKey, chainID, cli.EstimateGas, transactions) } diff --git a/internal/runtime/helper.go b/internal/runtime/helper.go index cc93bd2..2db7c64 100644 --- a/internal/runtime/helper.go +++ b/internal/runtime/helper.go @@ -128,3 +128,46 @@ func constructTransactions( return txs, nil } + +func calculateRuntimeCosts( + key crypto.PrivKey, + account std.Account, + transactions uint64, + chainID string, + getMsg msgFn, + estimateFn EstimateGasFn, +) (std.Coin, error) { + fmt.Printf("\n⏳ Estimating Gas ⏳\n") + + // Estimate the fee for the transaction batch + txFee := common.CalculateFeeInRatio( + 1_000_000, + common.DefaultGasPrice, + ) + + tx := &std.Tx{ + Msgs: []std.Msg{getMsg(account, 0)}, + Fee: txFee, + } + + // Sign the transaction + cfg := signer.SignCfg{ + ChainID: chainID, + AccountNumber: account.GetAccountNumber(), + Sequence: account.GetSequence(), + } + + if err := signer.SignTx(tx, key, cfg); err != nil { + return std.Coin{}, fmt.Errorf("unable to sign transaction, %w", err) + } + + estimatedGas, err := estimateFn(tx) + if err != nil { + return std.Coin{}, fmt.Errorf("unable to estimate gas, %w", err) + } + + return std.Coin{ + Denom: common.Denomination, + Amount: int64(transactions) * estimatedGas, + }, nil +} diff --git a/internal/runtime/package_deployment.go b/internal/runtime/package_deployment.go index 62cb52e..caf26f6 100644 --- a/internal/runtime/package_deployment.go +++ b/internal/runtime/package_deployment.go @@ -5,7 +5,6 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -26,6 +25,23 @@ func (c *packageDeployment) Initialize( return nil, nil } +func (c *packageDeployment) CalculateRuntimeCosts( + account std.Account, + key crypto.PrivKey, + chainID string, + estimateFn EstimateGasFn, + transactions uint64, +) (std.Coin, error) { + return calculateRuntimeCosts( + key, + account, + transactions, + chainID, + c.getMsgFn, + estimateFn, + ) +} + func (c *packageDeployment) ConstructTransactions( keys []crypto.PrivKey, accounts []std.Account, @@ -33,40 +49,42 @@ func (c *packageDeployment) ConstructTransactions( chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { - var ( - timestamp = time.Now().Unix() - - getMsgFn = func(creator std.Account, index int) std.Msg { - memPkg := &gnovm.MemPackage{ - Name: packageName, - Path: fmt.Sprintf( - "%s/%s/stress_%d_%d", - packagePathPrefix, - creator.GetAddress().String(), - timestamp, - index, - ), - Files: []*gnovm.MemFile{ - { - Name: packageFileName, - Body: packageBody, - }, - }, - } - - return vm.MsgAddPackage{ - Creator: creator.GetAddress(), - Package: memPkg, - } - } - ) - return constructTransactions( keys, accounts, transactions, chainID, - getMsgFn, + c.getMsgFn, estimateFn, ) } + +func (c *packageDeployment) getMsgFn(creator std.Account, index int) std.Msg { + timestamp := time.Now().Unix() + + memPkg := &std.MemPackage{ + Name: packageName, + Path: fmt.Sprintf( + "%s/%s/stress_%d_%d", + packagePathPrefix, + creator.GetAddress().String(), + timestamp, + index, + ), + Files: []*std.MemFile{ + { + Name: gnomodFileName, + Body: gnomodBody, + }, + { + Name: packageFileName, + Body: packageBody, + }, + }, + } + + return vm.MsgAddPackage{ + Creator: creator.GetAddress(), + Package: memPkg, + } +} diff --git a/internal/runtime/realm_call.go b/internal/runtime/realm_call.go index 157785d..9db7ed9 100644 --- a/internal/runtime/realm_call.go +++ b/internal/runtime/realm_call.go @@ -5,7 +5,6 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/supernova/internal/common" @@ -40,10 +39,14 @@ func (r *realmCall) Initialize( // Construct the transaction msg := vm.MsgAddPackage{ Creator: account.GetAddress(), - Package: &gnovm.MemPackage{ + Package: &std.MemPackage{ Name: packageName, Path: r.realmPath, - Files: []*gnovm.MemFile{ + Files: []*std.MemFile{ + { + Name: gnomodFileName, + Body: gnomodBody, + }, { Name: realmFileName, Body: realmBody, @@ -87,6 +90,23 @@ func (r *realmCall) Initialize( return []*std.Tx{tx}, nil } +func (r *realmCall) CalculateRuntimeCosts( + account std.Account, + key crypto.PrivKey, + chainID string, + estimateFn EstimateGasFn, + transactions uint64, +) (std.Coin, error) { + return calculateRuntimeCosts( + key, + account, + transactions, + chainID, + r.getMsgFn, + estimateFn, + ) +} + func (r *realmCall) ConstructTransactions( keys []crypto.PrivKey, accounts []std.Account, @@ -94,21 +114,21 @@ func (r *realmCall) ConstructTransactions( chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { - getMsgFn := func(creator std.Account, index int) std.Msg { - return vm.MsgCall{ - Caller: creator.GetAddress(), - PkgPath: r.realmPath, - Func: methodName, - Args: []string{fmt.Sprintf("Account-%d", index)}, - } - } - return constructTransactions( keys, accounts, transactions, chainID, - getMsgFn, + r.getMsgFn, estimateFn, ) } + +func (r *realmCall) getMsgFn(creator std.Account, index int) std.Msg { + return vm.MsgCall{ + Caller: creator.GetAddress(), + PkgPath: r.realmPath, + Func: methodName, + Args: []string{fmt.Sprintf("Account-%d", index)}, + } +} diff --git a/internal/runtime/realm_deployment.go b/internal/runtime/realm_deployment.go index 064477f..82114bd 100644 --- a/internal/runtime/realm_deployment.go +++ b/internal/runtime/realm_deployment.go @@ -5,7 +5,6 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -26,6 +25,52 @@ func (c *realmDeployment) Initialize( return nil, nil } +func (c *realmDeployment) CalculateRuntimeCosts( + account std.Account, + key crypto.PrivKey, + chainID string, + estimateFn EstimateGasFn, + transactions uint64, +) (std.Coin, error) { + return calculateRuntimeCosts( + key, + account, + transactions, + chainID, + c.getMsgFn, + estimateFn, + ) +} + +func (c *realmDeployment) getMsgFn(creator std.Account, index int) std.Msg { + timestamp := time.Now().Unix() + memPkg := &std.MemPackage{ + Name: packageName, + Path: fmt.Sprintf( + "%s/%s/stress_%d_%d", + realmPathPrefix, + creator.GetAddress().String(), + timestamp, + index, + ), + Files: []*std.MemFile{ + { + Name: gnomodFileName, + Body: gnomodBody, + }, + { + Name: realmFileName, + Body: realmBody, + }, + }, + } + + return vm.MsgAddPackage{ + Creator: creator.GetAddress(), + Package: memPkg, + } +} + func (c *realmDeployment) ConstructTransactions( keys []crypto.PrivKey, accounts []std.Account, @@ -33,40 +78,12 @@ func (c *realmDeployment) ConstructTransactions( chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { - var ( - timestamp = time.Now().Unix() - - getMsgFn = func(creator std.Account, index int) std.Msg { - memPkg := &gnovm.MemPackage{ - Name: packageName, - Path: fmt.Sprintf( - "%s/%s/stress_%d_%d", - realmPathPrefix, - creator.GetAddress().String(), - timestamp, - index, - ), - Files: []*gnovm.MemFile{ - { - Name: realmFileName, - Body: realmBody, - }, - }, - } - - return vm.MsgAddPackage{ - Creator: creator.GetAddress(), - Package: memPkg, - } - } - ) - return constructTransactions( keys, accounts, transactions, chainID, - getMsgFn, + c.getMsgFn, estimateFn, ) } diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go index 8915a7e..10f4723 100644 --- a/internal/runtime/runtime.go +++ b/internal/runtime/runtime.go @@ -27,6 +27,16 @@ type Runtime interface { chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) + // CalculateRuntimeCosts calculates the amount of funds + // each account needs to have in order to participate in the + // stress test run + CalculateRuntimeCosts( + account std.Account, + key crypto.PrivKey, + chainID string, + estimateFn EstimateGasFn, + transactions uint64, + ) (std.Coin, error) // ConstructTransactions generates and signs the required transactions // that will be used in the stress test diff --git a/internal/runtime/runtime_test.go b/internal/runtime/runtime_test.go index 4769fe5..52bd895 100644 --- a/internal/runtime/runtime_test.go +++ b/internal/runtime/runtime_test.go @@ -27,9 +27,9 @@ func verifyDeployTxCommon(t *testing.T, tx *std.Tx, expectedPrefix string) { // Make sure the deploy params are valid assert.Contains(t, vmMsg.Package.Path, expectedPrefix) - assert.Len(t, vmMsg.Package.Files, 1) + assert.Len(t, vmMsg.Package.Files, 2) assert.NotNil(t, vmMsg.Creator) - assert.Nil(t, vmMsg.Deposit) + assert.Nil(t, vmMsg.Send) // Make sure the fee is valid assert.Equal( diff --git a/internal/runtime/source.go b/internal/runtime/source.go index 7baa117..39fd280 100644 --- a/internal/runtime/source.go +++ b/internal/runtime/source.go @@ -48,6 +48,10 @@ func GetGreeting(language Language) string { return "Hello" } } +` + gnomodBody = ` +module = "gno.land/r/demo/runtime" +gno = "0.9" ` ) @@ -55,4 +59,5 @@ const ( packageName = "runtime" realmFileName = "realm.gno" packageFileName = "package.gno" + gnomodFileName = "gnomod.toml" ) From 506c30ba183744cb76ec77b8fda0afc4becd4f14 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Wed, 27 Aug 2025 16:15:55 +0200 Subject: [PATCH 2/8] adapt methods to crossing realm logic --- internal/runtime/realm_call.go | 3 ++- internal/runtime/source.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/runtime/realm_call.go b/internal/runtime/realm_call.go index 9db7ed9..eca5ac2 100644 --- a/internal/runtime/realm_call.go +++ b/internal/runtime/realm_call.go @@ -79,7 +79,7 @@ func (r *realmCall) Initialize( // Wipe the signatures, because we will change the fee, // and cause the previous ones to be invalid - clear(tx.Signatures) + tx.Signatures = make([]std.Signature, 0) tx.Fee = common.CalculateFeeInRatio(gasWanted+gasBuffer, common.DefaultGasPrice) // buffer with 10k gas @@ -125,6 +125,7 @@ func (r *realmCall) ConstructTransactions( } func (r *realmCall) getMsgFn(creator std.Account, index int) std.Msg { + fmt.Println("r.realmPath", r.realmPath) return vm.MsgCall{ Caller: creator.GetAddress(), PkgPath: r.realmPath, diff --git a/internal/runtime/source.go b/internal/runtime/source.go index 39fd280..9729bd5 100644 --- a/internal/runtime/source.go +++ b/internal/runtime/source.go @@ -11,7 +11,7 @@ func init() { // SayHello says hello to the specified name, using // the saved greeting -func SayHello(name string) string { +func SayHello(cur realm, name string) string { return greeting + " " + name + "!" } ` @@ -30,7 +30,7 @@ const ( // GetGreeting generates a greeting in // the specified language -func GetGreeting(language Language) string { +func GetGreeting(cur realm, language Language) string { switch language { case French: return "Bonjour" From 74a651d6603fb7ed70ae65aaf0adc922b35d4a10 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Wed, 27 Aug 2025 16:36:44 +0200 Subject: [PATCH 3/8] remove println --- internal/runtime/realm_call.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/runtime/realm_call.go b/internal/runtime/realm_call.go index eca5ac2..1d26875 100644 --- a/internal/runtime/realm_call.go +++ b/internal/runtime/realm_call.go @@ -125,7 +125,6 @@ func (r *realmCall) ConstructTransactions( } func (r *realmCall) getMsgFn(creator std.Account, index int) std.Msg { - fmt.Println("r.realmPath", r.realmPath) return vm.MsgCall{ Caller: creator.GetAddress(), PkgPath: r.realmPath, From ecdad574cfe22aa3118043e3dd175ea7ccb90f94 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Thu, 28 Aug 2025 20:57:51 +0200 Subject: [PATCH 4/8] pass max gas limit while simulating --- internal/common/common.go | 1 - internal/runtime/helper.go | 7 +++++-- internal/runtime/realm_call.go | 4 +++- internal/runtime/source.go | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/common/common.go b/internal/common/common.go index ffd3b73..0d004ab 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -19,7 +19,6 @@ var DefaultGasPrice = std.GasPrice{ func CalculateFeeInRatio(gasWanted int64, reference std.GasPrice) std.Fee { // required amount = ceil((gas wanted * reference.Price.Amount) / reference.Gas) requiredAmount := (gasWanted*reference.Price.Amount + reference.Gas - 1) / reference.Gas - return std.Fee{ GasWanted: gasWanted, GasFee: std.Coin{ diff --git a/internal/runtime/helper.go b/internal/runtime/helper.go index 2db7c64..579668f 100644 --- a/internal/runtime/helper.go +++ b/internal/runtime/helper.go @@ -3,6 +3,7 @@ package runtime import ( "fmt" + "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/supernova/internal/common" @@ -37,8 +38,9 @@ func constructTransactions( fmt.Printf("\n⏳ Estimating Gas ⏳\n") // Estimate the fee for the transaction batch + // passing in the maximum block gas, this is just a simulation txFee := common.CalculateFeeInRatio( - 1_000_000, + types.MaxBlockMaxGas, common.DefaultGasPrice, ) @@ -140,8 +142,9 @@ func calculateRuntimeCosts( fmt.Printf("\n⏳ Estimating Gas ⏳\n") // Estimate the fee for the transaction batch + // passing in the maximum block gas, this is just a simulation txFee := common.CalculateFeeInRatio( - 1_000_000, + types.MaxBlockMaxGas, common.DefaultGasPrice, ) diff --git a/internal/runtime/realm_call.go b/internal/runtime/realm_call.go index 1d26875..9af783e 100644 --- a/internal/runtime/realm_call.go +++ b/internal/runtime/realm_call.go @@ -5,6 +5,7 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/supernova/internal/common" @@ -57,7 +58,8 @@ func (r *realmCall) Initialize( tx := &std.Tx{ Msgs: []std.Msg{msg}, - Fee: common.CalculateFeeInRatio(1_000_000, common.DefaultGasPrice), + // passing in the maximum block gas, this is just a simulation + Fee: common.CalculateFeeInRatio(types.MaxBlockMaxGas, common.DefaultGasPrice), } // Sign it diff --git a/internal/runtime/source.go b/internal/runtime/source.go index 9729bd5..c936470 100644 --- a/internal/runtime/source.go +++ b/internal/runtime/source.go @@ -30,7 +30,7 @@ const ( // GetGreeting generates a greeting in // the specified language -func GetGreeting(cur realm, language Language) string { +func GetGreeting(language Language) string { switch language { case French: return "Bonjour" From 5a9cfbebfd8b56382b08da85903829aae82bfc05 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Fri, 29 Aug 2025 15:09:41 +0200 Subject: [PATCH 5/8] augment lint timeout --- .github/workflows/lint.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 25a58ac..609c77f 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -20,3 +20,4 @@ jobs: uses: golangci/golangci-lint-action@v6 with: version: v1.64 + args: --timeout=5m From b419e96310f0d2f8527f8b7a7ecd690d98f53552 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Fri, 29 Aug 2025 15:14:15 +0200 Subject: [PATCH 6/8] fix lint problem --- internal/common/common.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/common/common.go b/internal/common/common.go index 0d004ab..ffd3b73 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -19,6 +19,7 @@ var DefaultGasPrice = std.GasPrice{ func CalculateFeeInRatio(gasWanted int64, reference std.GasPrice) std.Fee { // required amount = ceil((gas wanted * reference.Price.Amount) / reference.Gas) requiredAmount := (gasWanted*reference.Price.Amount + reference.Gas - 1) / reference.Gas + return std.Fee{ GasWanted: gasWanted, GasFee: std.Coin{ From 257fe9dc26688c27583cf63c8cfdc5195787c09b Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Tue, 2 Sep 2025 11:11:38 +0200 Subject: [PATCH 7/8] compute max gas amount on last block --- internal/pipeline.go | 22 +++++++++++++---- internal/runtime/helper.go | 33 ++++++++++++++++---------- internal/runtime/helper_test.go | 1 + internal/runtime/package_deployment.go | 14 ++++++----- internal/runtime/realm_call.go | 32 ++++++++++--------------- internal/runtime/realm_deployment.go | 14 ++++++----- internal/runtime/runtime.go | 12 ++++++---- internal/runtime/runtime_test.go | 14 +++++++---- 8 files changed, 86 insertions(+), 56 deletions(-) diff --git a/internal/pipeline.go b/internal/pipeline.go index f27fa54..522f54c 100644 --- a/internal/pipeline.go +++ b/internal/pipeline.go @@ -66,6 +66,15 @@ func (p *Pipeline) Execute() error { // Initialize the accounts for the runtime accounts := p.initializeAccounts() + lastBlock, err := p.cli.GetLatestBlockHeight() + if err != nil { + return fmt.Errorf("unable to get last block, %w", err) + } + + maxGas, err := p.cli.GetBlockGasLimit(lastBlock) + if err != nil { + return fmt.Errorf("unable to get block gas limit, %w", err) + } // Predeploy any pending transactions estimatedGas, err := prepareRuntime( mode, @@ -73,6 +82,7 @@ func (p *Pipeline) Execute() error { p.cfg.ChainID, p.cli, txRuntime, + maxGas, p.cfg.Transactions, ) if err != nil { @@ -112,6 +122,7 @@ func (p *Pipeline) Execute() error { runKeys, runAccounts, p.cfg.Transactions, + maxGas, p.cfg.ChainID, p.cli.EstimateGas, ) @@ -195,6 +206,7 @@ func prepareRuntime( chainID string, cli pipelineClient, txRuntime runtime.Runtime, + currentMaxGas int64, transactions uint64, ) (std.Coin, error) { // Get the deployer account @@ -203,8 +215,10 @@ func prepareRuntime( return std.Coin{}, fmt.Errorf("unable to fetch deployer account, %w", err) } + signCB := runtime.SignTransactionsCb(chainID, deployer, deployerKey) + if mode != runtime.RealmCall { - return txRuntime.CalculateRuntimeCosts(deployer, deployerKey, chainID, cli.EstimateGas, transactions) + return txRuntime.CalculateRuntimeCosts(deployer, cli.EstimateGas, signCB, currentMaxGas, transactions) } fmt.Printf("\n✨ Starting Predeployment Procedure ✨\n\n") @@ -212,9 +226,9 @@ func prepareRuntime( // Get the predeploy transactions predeployTxs, err := txRuntime.Initialize( deployer, - deployerKey, - chainID, + signCB, cli.EstimateGas, + currentMaxGas, ) if err != nil { return std.Coin{}, fmt.Errorf("unable to initialize runtime, %w", err) @@ -233,5 +247,5 @@ func prepareRuntime( fmt.Printf("✅ Successfully predeployed %d transactions\n", len(predeployTxs)) - return txRuntime.CalculateRuntimeCosts(deployer, deployerKey, chainID, cli.EstimateGas, transactions) + return txRuntime.CalculateRuntimeCosts(deployer, cli.EstimateGas, signCB, currentMaxGas, transactions) } diff --git a/internal/runtime/helper.go b/internal/runtime/helper.go index 579668f..0b8f135 100644 --- a/internal/runtime/helper.go +++ b/internal/runtime/helper.go @@ -3,7 +3,6 @@ package runtime import ( "fmt" - "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/supernova/internal/common" @@ -22,6 +21,7 @@ func constructTransactions( keys []crypto.PrivKey, accounts []std.Account, transactions uint64, + maxGas int64, chainID string, getMsg msgFn, estimateFn EstimateGasFn, @@ -40,7 +40,7 @@ func constructTransactions( // Estimate the fee for the transaction batch // passing in the maximum block gas, this is just a simulation txFee := common.CalculateFeeInRatio( - types.MaxBlockMaxGas, + maxGas, common.DefaultGasPrice, ) @@ -132,11 +132,11 @@ func constructTransactions( } func calculateRuntimeCosts( - key crypto.PrivKey, account std.Account, transactions uint64, - chainID string, + maxBlockMaxGas int64, getMsg msgFn, + signFn SignFn, estimateFn EstimateGasFn, ) (std.Coin, error) { fmt.Printf("\n⏳ Estimating Gas ⏳\n") @@ -144,7 +144,7 @@ func calculateRuntimeCosts( // Estimate the fee for the transaction batch // passing in the maximum block gas, this is just a simulation txFee := common.CalculateFeeInRatio( - types.MaxBlockMaxGas, + maxBlockMaxGas, common.DefaultGasPrice, ) @@ -153,14 +153,8 @@ func calculateRuntimeCosts( Fee: txFee, } - // Sign the transaction - cfg := signer.SignCfg{ - ChainID: chainID, - AccountNumber: account.GetAccountNumber(), - Sequence: account.GetSequence(), - } - - if err := signer.SignTx(tx, key, cfg); err != nil { + err := signFn(tx) + if err != nil { return std.Coin{}, fmt.Errorf("unable to sign transaction, %w", err) } @@ -174,3 +168,16 @@ func calculateRuntimeCosts( Amount: int64(transactions) * estimatedGas, }, nil } + +func SignTransactionsCb(chainID string, account std.Account, key crypto.PrivKey) SignFn { + // Sign the transaction + cfg := signer.SignCfg{ + ChainID: chainID, + AccountNumber: account.GetAccountNumber(), + Sequence: account.GetSequence(), + } + + return func(tx *std.Tx) error { + return signer.SignTx(tx, key, cfg) + } +} diff --git a/internal/runtime/helper_test.go b/internal/runtime/helper_test.go index a12006a..4a79b5e 100644 --- a/internal/runtime/helper_test.go +++ b/internal/runtime/helper_test.go @@ -54,6 +54,7 @@ func TestHelper_ConstructTransactions(t *testing.T) { accountKeys, accounts, transactions, + 1_000_000, "dummy", getMsgFn, func(_ *std.Tx) (int64, error) { diff --git a/internal/runtime/package_deployment.go b/internal/runtime/package_deployment.go index caf26f6..cdaa728 100644 --- a/internal/runtime/package_deployment.go +++ b/internal/runtime/package_deployment.go @@ -17,9 +17,9 @@ func newPackageDeployment() *packageDeployment { func (c *packageDeployment) Initialize( _ std.Account, - _ crypto.PrivKey, - _ string, + _ SignFn, _ EstimateGasFn, + _ int64, ) ([]*std.Tx, error) { // No extra setup needed for this runtime type return nil, nil @@ -27,17 +27,17 @@ func (c *packageDeployment) Initialize( func (c *packageDeployment) CalculateRuntimeCosts( account std.Account, - key crypto.PrivKey, - chainID string, estimateFn EstimateGasFn, + signFn SignFn, + currentMaxGas int64, transactions uint64, ) (std.Coin, error) { return calculateRuntimeCosts( - key, account, transactions, - chainID, + currentMaxGas, c.getMsgFn, + signFn, estimateFn, ) } @@ -46,6 +46,7 @@ func (c *packageDeployment) ConstructTransactions( keys []crypto.PrivKey, accounts []std.Account, transactions uint64, + maxGas int64, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { @@ -53,6 +54,7 @@ func (c *packageDeployment) ConstructTransactions( keys, accounts, transactions, + maxGas, chainID, c.getMsgFn, estimateFn, diff --git a/internal/runtime/realm_call.go b/internal/runtime/realm_call.go index 9af783e..9682dcf 100644 --- a/internal/runtime/realm_call.go +++ b/internal/runtime/realm_call.go @@ -5,11 +5,9 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/supernova/internal/common" - "github.com/gnolang/supernova/internal/signer" ) const methodName = "SayHello" @@ -24,9 +22,9 @@ func newRealmCall() *realmCall { func (r *realmCall) Initialize( account std.Account, - key crypto.PrivKey, - chainID string, + signFn SignFn, estimateFn EstimateGasFn, + currentMaxGas int64, ) ([]*std.Tx, error) { // The Realm needs to be deployed before // it can be interacted with @@ -59,17 +57,11 @@ func (r *realmCall) Initialize( tx := &std.Tx{ Msgs: []std.Msg{msg}, // passing in the maximum block gas, this is just a simulation - Fee: common.CalculateFeeInRatio(types.MaxBlockMaxGas, common.DefaultGasPrice), - } - - // Sign it - cfg := signer.SignCfg{ - ChainID: chainID, - AccountNumber: account.GetAccountNumber(), - Sequence: account.GetSequence(), + Fee: common.CalculateFeeInRatio(currentMaxGas, common.DefaultGasPrice), } - if err := signer.SignTx(tx, key, cfg); err != nil { + err := signFn(tx) + if err != nil { return nil, fmt.Errorf("unable to sign initialize transaction, %w", err) } @@ -82,10 +74,10 @@ func (r *realmCall) Initialize( // Wipe the signatures, because we will change the fee, // and cause the previous ones to be invalid tx.Signatures = make([]std.Signature, 0) - tx.Fee = common.CalculateFeeInRatio(gasWanted+gasBuffer, common.DefaultGasPrice) // buffer with 10k gas - if err = signer.SignTx(tx, key, cfg); err != nil { + err = signFn(tx) + if err != nil { return nil, fmt.Errorf("unable to sign initialize transaction, %w", err) } @@ -94,17 +86,17 @@ func (r *realmCall) Initialize( func (r *realmCall) CalculateRuntimeCosts( account std.Account, - key crypto.PrivKey, - chainID string, estimateFn EstimateGasFn, + signFn SignFn, + currentMaxGas int64, transactions uint64, ) (std.Coin, error) { return calculateRuntimeCosts( - key, account, transactions, - chainID, + currentMaxGas, r.getMsgFn, + signFn, estimateFn, ) } @@ -113,6 +105,7 @@ func (r *realmCall) ConstructTransactions( keys []crypto.PrivKey, accounts []std.Account, transactions uint64, + maxGas int64, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { @@ -120,6 +113,7 @@ func (r *realmCall) ConstructTransactions( keys, accounts, transactions, + maxGas, chainID, r.getMsgFn, estimateFn, diff --git a/internal/runtime/realm_deployment.go b/internal/runtime/realm_deployment.go index 82114bd..bf503c5 100644 --- a/internal/runtime/realm_deployment.go +++ b/internal/runtime/realm_deployment.go @@ -17,9 +17,9 @@ func newRealmDeployment() *realmDeployment { func (c *realmDeployment) Initialize( _ std.Account, - _ crypto.PrivKey, - _ string, + _ SignFn, _ EstimateGasFn, + _ int64, ) ([]*std.Tx, error) { // No extra setup needed for this runtime type return nil, nil @@ -27,17 +27,17 @@ func (c *realmDeployment) Initialize( func (c *realmDeployment) CalculateRuntimeCosts( account std.Account, - key crypto.PrivKey, - chainID string, estimateFn EstimateGasFn, + signFn SignFn, + currentMaxGas int64, transactions uint64, ) (std.Coin, error) { return calculateRuntimeCosts( - key, account, transactions, - chainID, + currentMaxGas, c.getMsgFn, + signFn, estimateFn, ) } @@ -75,6 +75,7 @@ func (c *realmDeployment) ConstructTransactions( keys []crypto.PrivKey, accounts []std.Account, transactions uint64, + maxGas int64, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { @@ -82,6 +83,7 @@ func (c *realmDeployment) ConstructTransactions( keys, accounts, transactions, + maxGas, chainID, c.getMsgFn, estimateFn, diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go index 10f4723..96fa1a6 100644 --- a/internal/runtime/runtime.go +++ b/internal/runtime/runtime.go @@ -13,6 +13,9 @@ const ( // EstimateGasFn is the gas estimation callback type EstimateGasFn func(tx *std.Tx) (int64, error) +// SignFn is the tx signing callback +type SignFn func(tx *std.Tx) error + // Runtime is the base interface for all runtime // implementations. // @@ -23,18 +26,18 @@ type Runtime interface { // to be executed before the stress test runs, if any Initialize( account std.Account, - key crypto.PrivKey, - chainID string, + signFn SignFn, estimateFn EstimateGasFn, + currentMaxGas int64, ) ([]*std.Tx, error) // CalculateRuntimeCosts calculates the amount of funds // each account needs to have in order to participate in the // stress test run CalculateRuntimeCosts( account std.Account, - key crypto.PrivKey, - chainID string, estimateFn EstimateGasFn, + signFn SignFn, + currentMaxGas int64, transactions uint64, ) (std.Coin, error) @@ -44,6 +47,7 @@ type Runtime interface { keys []crypto.PrivKey, accounts []std.Account, transactions uint64, + maxGas int64, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) diff --git a/internal/runtime/runtime_test.go b/internal/runtime/runtime_test.go index 52bd895..0c27f1b 100644 --- a/internal/runtime/runtime_test.go +++ b/internal/runtime/runtime_test.go @@ -75,11 +75,13 @@ func TestRuntime_CommonDeployment(t *testing.T) { // Make sure there is no initialization logic initialTxs, err := r.Initialize( accounts[0], - accountKeys[0], - "dummy", + func(_ *std.Tx) error { + return nil + }, func(_ *std.Tx) (int64, error) { return 1_000_000, nil }, + 1_000_000, ) assert.Nil(t, initialTxs) @@ -90,6 +92,7 @@ func TestRuntime_CommonDeployment(t *testing.T) { accountKeys, accounts, transactions, + 1_000_000, "dummy", func(_ *std.Tx) (int64, error) { return 1_000_000, nil @@ -126,11 +129,13 @@ func TestRuntime_RealmCall(t *testing.T) { // Make sure the initialization logic is present initialTxs, err := r.Initialize( accounts[0], - accountKeys[0], - "dummy", + func(_ *std.Tx) error { + return nil + }, func(_ *std.Tx) (int64, error) { return 1_000_000, nil }, + 1_000_000, ) if err != nil { t.Fatalf("unable to generate init transactions, %v", err) @@ -149,6 +154,7 @@ func TestRuntime_RealmCall(t *testing.T) { accountKeys[1:], accounts[1:], transactions, + 1_000_000, "dummy", func(_ *std.Tx) (int64, error) { return 1_000_000, nil From 14c58b1f818933f15c8d32c82673468be43e6a5b Mon Sep 17 00:00:00 2001 From: Miguel Victoria Date: Tue, 2 Sep 2025 14:00:59 +0200 Subject: [PATCH 8/8] take gas price from pipeline --- internal/client/client.go | 22 +++++++++++++++++++++- internal/distributor/distributor.go | 7 +++++-- internal/distributor/distributor_test.go | 6 +++--- internal/distributor/mock_test.go | 10 ++++++++++ internal/pipeline.go | 14 ++++++++++++-- internal/runtime/helper.go | 8 +++++--- internal/runtime/helper_test.go | 1 + internal/runtime/package_deployment.go | 5 +++++ internal/runtime/realm_call.go | 9 +++++++-- internal/runtime/realm_deployment.go | 5 +++++ internal/runtime/runtime.go | 3 +++ internal/runtime/runtime_test.go | 4 ++++ 12 files changed, 81 insertions(+), 13 deletions(-) diff --git a/internal/client/client.go b/internal/client/client.go index ac771ae..1e08c70 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -12,7 +12,10 @@ import ( "github.com/gnolang/supernova/internal/common" ) -const simulatePath = ".app/simulate" +const ( + simulatePath = ".app/simulate" + gaspricePath = "auth/gasprice" +) type Client struct { conn *client.RPCClient @@ -170,3 +173,20 @@ func (h *Client) EstimateGas(tx *std.Tx) (int64, error) { // for executing the transaction return deliverTx.GasUsed, nil } + +func (h *Client) FetchGasPrice() (std.GasPrice, error) { + // Perform auth/gasprice + gp := std.GasPrice{} + + qres, err := h.conn.ABCIQuery(gaspricePath, []byte{}) + if err != nil { + return gp, err + } + + err = amino.UnmarshalJSON(qres.Response.Data, &gp) + if err != nil { + return gp, err + } + + return gp, nil +} diff --git a/internal/distributor/distributor.go b/internal/distributor/distributor.go index cc4bfbb..c278b2f 100644 --- a/internal/distributor/distributor.go +++ b/internal/distributor/distributor.go @@ -20,6 +20,7 @@ type Client interface { GetAccount(address string) (*gnoland.GnoAccount, error) BroadcastTransaction(tx *std.Tx) error EstimateGas(tx *std.Tx) (int64, error) + FetchGasPrice() (std.GasPrice, error) } // Distributor is the process @@ -43,6 +44,7 @@ func (d *Distributor) Distribute( distributor crypto.PrivKey, accounts []crypto.Address, chainID string, + gasPrice std.GasPrice, calculatedRuntimeCost std.Coin, ) ([]std.Account, error) { fmt.Printf("\n💸 Starting Fund Distribution 💸\n\n") @@ -54,7 +56,7 @@ func (d *Distributor) Distribute( ) // Fund the accounts - return d.fundAccounts(distributor, accounts, calculatedRuntimeCost, chainID) + return d.fundAccounts(distributor, accounts, calculatedRuntimeCost, chainID, gasPrice) } // fundAccounts attempts to fund accounts that have missing funds, @@ -64,6 +66,7 @@ func (d *Distributor) fundAccounts( accounts []crypto.Address, singleRunCost std.Coin, chainID string, + gasPrice std.GasPrice, ) ([]std.Account, error) { type shortAccount struct { missingFunds std.Coin @@ -128,7 +131,7 @@ func (d *Distributor) fundAccounts( var ( distributorBalance = distributor.Coins fundableIndex = 0 - defaultFee = common.CalculateFeeInRatio(100_000, common.DefaultGasPrice) + defaultFee = common.CalculateFeeInRatio(100_000, gasPrice) ) for _, account := range shortAccounts { diff --git a/internal/distributor/distributor_test.go b/internal/distributor/distributor_test.go index 3454128..c3ae019 100644 --- a/internal/distributor/distributor_test.go +++ b/internal/distributor/distributor_test.go @@ -69,7 +69,7 @@ func TestDistributor_Distribute(t *testing.T) { addresses = append(addresses, account.PubKey().Address()) } - readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", singleCost) + readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", common.DefaultGasPrice, singleCost) if err != nil { t.Fatalf("unable to distribute funds, %v", err) } @@ -125,7 +125,7 @@ func TestDistributor_Distribute(t *testing.T) { addresses = append(addresses, account.PubKey().Address()) } - readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", singleCost) + readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", common.DefaultGasPrice, singleCost) assert.Nil(t, readyAccounts) assert.ErrorIs(t, err, errInsufficientFunds) @@ -195,7 +195,7 @@ func TestDistributor_Distribute(t *testing.T) { addresses = append(addresses, account.PubKey().Address()) } - readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", singleCost) + readyAccounts, err := d.Distribute(accounts[0], addresses, "dummy", common.DefaultGasPrice, singleCost) if err != nil { t.Fatalf("unable to distribute funds, %v", err) } diff --git a/internal/distributor/mock_test.go b/internal/distributor/mock_test.go index bd9cd1b..5d30456 100644 --- a/internal/distributor/mock_test.go +++ b/internal/distributor/mock_test.go @@ -9,12 +9,14 @@ type ( broadcastTransactionDelegate func(*std.Tx) error getAccountDelegate func(string) (*gnoland.GnoAccount, error) estimateGasDelegate func(*std.Tx) (int64, error) + fetchGasPriceDelegate func() (std.GasPrice, error) ) type mockClient struct { broadcastTransactionFn broadcastTransactionDelegate getAccountFn getAccountDelegate estimateGasFn estimateGasDelegate + fetchGasPriceFn fetchGasPriceDelegate } func (m *mockClient) BroadcastTransaction(tx *std.Tx) error { @@ -40,3 +42,11 @@ func (m *mockClient) EstimateGas(tx *std.Tx) (int64, error) { return 0, nil } + +func (m *mockClient) FetchGasPrice() (std.GasPrice, error) { + if m.fetchGasPriceFn != nil { + return m.fetchGasPriceFn() + } + + return std.GasPrice{}, nil +} diff --git a/internal/pipeline.go b/internal/pipeline.go index 522f54c..9a278ce 100644 --- a/internal/pipeline.go +++ b/internal/pipeline.go @@ -66,6 +66,11 @@ func (p *Pipeline) Execute() error { // Initialize the accounts for the runtime accounts := p.initializeAccounts() + gasPrice, err := p.cli.FetchGasPrice() + if err != nil { + return err + } + lastBlock, err := p.cli.GetLatestBlockHeight() if err != nil { return fmt.Errorf("unable to get last block, %w", err) @@ -83,6 +88,7 @@ func (p *Pipeline) Execute() error { p.cli, txRuntime, maxGas, + gasPrice, p.cfg.Transactions, ) if err != nil { @@ -100,6 +106,7 @@ func (p *Pipeline) Execute() error { accounts[0], addresses, p.cfg.ChainID, + gasPrice, estimatedGas, ) if err != nil { @@ -123,6 +130,7 @@ func (p *Pipeline) Execute() error { runAccounts, p.cfg.Transactions, maxGas, + gasPrice, p.cfg.ChainID, p.cli.EstimateGas, ) @@ -207,6 +215,7 @@ func prepareRuntime( cli pipelineClient, txRuntime runtime.Runtime, currentMaxGas int64, + gasPrice std.GasPrice, transactions uint64, ) (std.Coin, error) { // Get the deployer account @@ -218,7 +227,7 @@ func prepareRuntime( signCB := runtime.SignTransactionsCb(chainID, deployer, deployerKey) if mode != runtime.RealmCall { - return txRuntime.CalculateRuntimeCosts(deployer, cli.EstimateGas, signCB, currentMaxGas, transactions) + return txRuntime.CalculateRuntimeCosts(deployer, cli.EstimateGas, signCB, currentMaxGas, gasPrice, transactions) } fmt.Printf("\n✨ Starting Predeployment Procedure ✨\n\n") @@ -229,6 +238,7 @@ func prepareRuntime( signCB, cli.EstimateGas, currentMaxGas, + gasPrice, ) if err != nil { return std.Coin{}, fmt.Errorf("unable to initialize runtime, %w", err) @@ -247,5 +257,5 @@ func prepareRuntime( fmt.Printf("✅ Successfully predeployed %d transactions\n", len(predeployTxs)) - return txRuntime.CalculateRuntimeCosts(deployer, cli.EstimateGas, signCB, currentMaxGas, transactions) + return txRuntime.CalculateRuntimeCosts(deployer, cli.EstimateGas, signCB, currentMaxGas, gasPrice, transactions) } diff --git a/internal/runtime/helper.go b/internal/runtime/helper.go index 0b8f135..7c791df 100644 --- a/internal/runtime/helper.go +++ b/internal/runtime/helper.go @@ -22,6 +22,7 @@ func constructTransactions( accounts []std.Account, transactions uint64, maxGas int64, + gasPrice std.GasPrice, chainID string, getMsg msgFn, estimateFn EstimateGasFn, @@ -41,7 +42,7 @@ func constructTransactions( // passing in the maximum block gas, this is just a simulation txFee := common.CalculateFeeInRatio( maxGas, - common.DefaultGasPrice, + gasPrice, ) // Construct the first tx @@ -76,7 +77,7 @@ func constructTransactions( clear(tx.Signatures) // Use the estimated gas limit - txFee = common.CalculateFeeInRatio(gasWanted+gasBuffer, common.DefaultGasPrice) // 10k gas buffer + txFee = common.CalculateFeeInRatio(gasWanted+gasBuffer, gasPrice) // 10k gas buffer if err = signer.SignTx(tx, creatorKey, cfg); err != nil { return nil, fmt.Errorf("unable to sign transaction, %w", err) @@ -135,6 +136,7 @@ func calculateRuntimeCosts( account std.Account, transactions uint64, maxBlockMaxGas int64, + gasPrice std.GasPrice, getMsg msgFn, signFn SignFn, estimateFn EstimateGasFn, @@ -145,7 +147,7 @@ func calculateRuntimeCosts( // passing in the maximum block gas, this is just a simulation txFee := common.CalculateFeeInRatio( maxBlockMaxGas, - common.DefaultGasPrice, + gasPrice, ) tx := &std.Tx{ diff --git a/internal/runtime/helper_test.go b/internal/runtime/helper_test.go index 4a79b5e..6e4ad13 100644 --- a/internal/runtime/helper_test.go +++ b/internal/runtime/helper_test.go @@ -55,6 +55,7 @@ func TestHelper_ConstructTransactions(t *testing.T) { accounts, transactions, 1_000_000, + common.DefaultGasPrice, "dummy", getMsgFn, func(_ *std.Tx) (int64, error) { diff --git a/internal/runtime/package_deployment.go b/internal/runtime/package_deployment.go index cdaa728..330dbf4 100644 --- a/internal/runtime/package_deployment.go +++ b/internal/runtime/package_deployment.go @@ -20,6 +20,7 @@ func (c *packageDeployment) Initialize( _ SignFn, _ EstimateGasFn, _ int64, + _ std.GasPrice, ) ([]*std.Tx, error) { // No extra setup needed for this runtime type return nil, nil @@ -30,12 +31,14 @@ func (c *packageDeployment) CalculateRuntimeCosts( estimateFn EstimateGasFn, signFn SignFn, currentMaxGas int64, + gasPrice std.GasPrice, transactions uint64, ) (std.Coin, error) { return calculateRuntimeCosts( account, transactions, currentMaxGas, + gasPrice, c.getMsgFn, signFn, estimateFn, @@ -47,6 +50,7 @@ func (c *packageDeployment) ConstructTransactions( accounts []std.Account, transactions uint64, maxGas int64, + gasPrice std.GasPrice, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { @@ -55,6 +59,7 @@ func (c *packageDeployment) ConstructTransactions( accounts, transactions, maxGas, + gasPrice, chainID, c.getMsgFn, estimateFn, diff --git a/internal/runtime/realm_call.go b/internal/runtime/realm_call.go index 9682dcf..aa3cc0e 100644 --- a/internal/runtime/realm_call.go +++ b/internal/runtime/realm_call.go @@ -25,6 +25,7 @@ func (r *realmCall) Initialize( signFn SignFn, estimateFn EstimateGasFn, currentMaxGas int64, + gasPrice std.GasPrice, ) ([]*std.Tx, error) { // The Realm needs to be deployed before // it can be interacted with @@ -57,7 +58,7 @@ func (r *realmCall) Initialize( tx := &std.Tx{ Msgs: []std.Msg{msg}, // passing in the maximum block gas, this is just a simulation - Fee: common.CalculateFeeInRatio(currentMaxGas, common.DefaultGasPrice), + Fee: common.CalculateFeeInRatio(currentMaxGas, gasPrice), } err := signFn(tx) @@ -74,7 +75,7 @@ func (r *realmCall) Initialize( // Wipe the signatures, because we will change the fee, // and cause the previous ones to be invalid tx.Signatures = make([]std.Signature, 0) - tx.Fee = common.CalculateFeeInRatio(gasWanted+gasBuffer, common.DefaultGasPrice) // buffer with 10k gas + tx.Fee = common.CalculateFeeInRatio(gasWanted+gasBuffer, gasPrice) // buffer with 10k gas err = signFn(tx) if err != nil { @@ -89,12 +90,14 @@ func (r *realmCall) CalculateRuntimeCosts( estimateFn EstimateGasFn, signFn SignFn, currentMaxGas int64, + gasPrice std.GasPrice, transactions uint64, ) (std.Coin, error) { return calculateRuntimeCosts( account, transactions, currentMaxGas, + gasPrice, r.getMsgFn, signFn, estimateFn, @@ -106,6 +109,7 @@ func (r *realmCall) ConstructTransactions( accounts []std.Account, transactions uint64, maxGas int64, + gasPrice std.GasPrice, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { @@ -114,6 +118,7 @@ func (r *realmCall) ConstructTransactions( accounts, transactions, maxGas, + gasPrice, chainID, r.getMsgFn, estimateFn, diff --git a/internal/runtime/realm_deployment.go b/internal/runtime/realm_deployment.go index bf503c5..daa54d5 100644 --- a/internal/runtime/realm_deployment.go +++ b/internal/runtime/realm_deployment.go @@ -20,6 +20,7 @@ func (c *realmDeployment) Initialize( _ SignFn, _ EstimateGasFn, _ int64, + _ std.GasPrice, ) ([]*std.Tx, error) { // No extra setup needed for this runtime type return nil, nil @@ -30,12 +31,14 @@ func (c *realmDeployment) CalculateRuntimeCosts( estimateFn EstimateGasFn, signFn SignFn, currentMaxGas int64, + gasPrice std.GasPrice, transactions uint64, ) (std.Coin, error) { return calculateRuntimeCosts( account, transactions, currentMaxGas, + gasPrice, c.getMsgFn, signFn, estimateFn, @@ -76,6 +79,7 @@ func (c *realmDeployment) ConstructTransactions( accounts []std.Account, transactions uint64, maxGas int64, + gasPrice std.GasPrice, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) { @@ -84,6 +88,7 @@ func (c *realmDeployment) ConstructTransactions( accounts, transactions, maxGas, + gasPrice, chainID, c.getMsgFn, estimateFn, diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go index 96fa1a6..219d1b6 100644 --- a/internal/runtime/runtime.go +++ b/internal/runtime/runtime.go @@ -29,6 +29,7 @@ type Runtime interface { signFn SignFn, estimateFn EstimateGasFn, currentMaxGas int64, + gasPrice std.GasPrice, ) ([]*std.Tx, error) // CalculateRuntimeCosts calculates the amount of funds // each account needs to have in order to participate in the @@ -38,6 +39,7 @@ type Runtime interface { estimateFn EstimateGasFn, signFn SignFn, currentMaxGas int64, + gasPrice std.GasPrice, transactions uint64, ) (std.Coin, error) @@ -48,6 +50,7 @@ type Runtime interface { accounts []std.Account, transactions uint64, maxGas int64, + gasPrice std.GasPrice, chainID string, estimateFn EstimateGasFn, ) ([]*std.Tx, error) diff --git a/internal/runtime/runtime_test.go b/internal/runtime/runtime_test.go index 0c27f1b..f3ac770 100644 --- a/internal/runtime/runtime_test.go +++ b/internal/runtime/runtime_test.go @@ -82,6 +82,7 @@ func TestRuntime_CommonDeployment(t *testing.T) { return 1_000_000, nil }, 1_000_000, + common.DefaultGasPrice, ) assert.Nil(t, initialTxs) @@ -93,6 +94,7 @@ func TestRuntime_CommonDeployment(t *testing.T) { accounts, transactions, 1_000_000, + common.DefaultGasPrice, "dummy", func(_ *std.Tx) (int64, error) { return 1_000_000, nil @@ -136,6 +138,7 @@ func TestRuntime_RealmCall(t *testing.T) { return 1_000_000, nil }, 1_000_000, + common.DefaultGasPrice, ) if err != nil { t.Fatalf("unable to generate init transactions, %v", err) @@ -155,6 +158,7 @@ func TestRuntime_RealmCall(t *testing.T) { accounts[1:], transactions, 1_000_000, + common.DefaultGasPrice, "dummy", func(_ *std.Tx) (int64, error) { return 1_000_000, nil