From 93fb5f50fe7c769810e5bdbedc7a26907b2f8c5b Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Tue, 18 Nov 2025 16:51:49 -0500 Subject: [PATCH 01/14] Initial boilerplate for benchmarking new transactions. --- bbq/vm/test/transactions_test.go | 131 +++++++++++++++++++++++++++++++ go.mod | 23 +++--- go.sum | 35 ++++++--- 3 files changed, 167 insertions(+), 22 deletions(-) create mode 100644 bbq/vm/test/transactions_test.go diff --git a/bbq/vm/test/transactions_test.go b/bbq/vm/test/transactions_test.go new file mode 100644 index 000000000..3e0b10873 --- /dev/null +++ b/bbq/vm/test/transactions_test.go @@ -0,0 +1,131 @@ +/* +* Cadence - The resource-oriented smart contract programming language +* +* Copyright Flow Foundation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +package test + +import ( + "fmt" + "testing" + + "github.com/onflow/cadence-standard-transactions/transactions" + . "github.com/onflow/cadence/bbq/test_utils" + "github.com/onflow/cadence/bbq/vm" + "github.com/onflow/cadence/common" + "github.com/onflow/cadence/interpreter" + "github.com/onflow/cadence/stdlib" + . "github.com/onflow/cadence/test_utils/interpreter_utils" + . "github.com/onflow/cadence/test_utils/sema_utils" + "github.com/stretchr/testify/require" +) + +type Transaction struct { + Name string + Body string +} + +var testTransactions []Transaction + +func createTransaction(name string, imports string, prepare string) Transaction { + return Transaction{ + Name: name, + Body: fmt.Sprintf( + ` + // %s + %s + + transaction(){ + prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { + var f: fun(): Void = fun(){} + f = fun() { %s } + f() + } + }`, + name, + imports, + prepare, + ), + } +} + +func init() { + testTransactions = []Transaction{ + createTransaction("EmptyLoopTransaction", "", transactions.EmptyLoopTransaction(5000).GetPrepareBlock()), + } +} + +func BenchmarkTransactions(b *testing.B) { + vmConfig := vm.NewConfig(NewUnmeteredInMemoryStorage()) + + // Set up account handler for creating signers + vmConfig.AccountHandlerFunc = func( + context interpreter.AccountCreationContext, + address interpreter.AddressValue, + ) interpreter.Value { + return stdlib.NewAccountValue(context, nil, address) + } + + // Create a signer address + signerAddress := interpreter.NewUnmeteredAddressValueFromBytes([]byte{0x1}) + + for _, transaction := range testTransactions { + + b.Run(transaction.Name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + + vmInstance, err := CompileAndPrepareToInvoke( + b, + transaction.Body, + CompilerAndVMOptions{ + VMConfig: vmConfig, + ParseCheckAndCompileOptions: ParseCheckAndCompileOptions{ + ParseAndCheckOptions: &ParseAndCheckOptions{ + Location: common.TransactionLocation{}, + }, + }, + }, + ) + require.NoError(b, err) + + // Create signer for the transaction + signer := stdlib.NewAccountReferenceValue( + vmInstance.Context(), + nil, + signerAddress, + interpreter.FullyEntitledAccountAccess, + ) + + err = vmInstance.InvokeTransaction(nil, signer) + require.NoError(b, err) + + // Rerun the same again using internal functions, to get the access to the transaction value. + + transaction, err := vmInstance.InvokeTransactionWrapper() + require.NoError(b, err) + + b.StartTimer() + + // Invoke 'prepare' with signer + err = vmInstance.InvokeTransactionPrepare(transaction, []vm.Value{signer}) + + b.StopTimer() + require.NoError(b, err) + } + }) + } +} diff --git a/go.mod b/go.mod index 89307e748..23d3ddc36 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/onflow/cadence -go 1.24.0 - -toolchain go1.24.3 +go 1.25.0 require ( github.com/SaveTheRbtz/mph v0.1.1-0.20240117162131-4166ec7869bc @@ -19,6 +17,7 @@ require ( github.com/leanovate/gopter v0.2.11 github.com/logrusorgru/aurora/v4 v4.0.0 github.com/onflow/atree v0.12.0 + github.com/onflow/cadence-standard-transactions v0.0.0-20251118182655-c31f418b74bc github.com/onflow/crypto v0.25.3 github.com/onflow/fixed-point v0.1.1 github.com/rivo/uniseg v0.4.7 @@ -37,28 +36,32 @@ require ( ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/fxamacker/circlehash v0.3.0 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect - github.com/klauspost/cpuid/v2 v2.2.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-tty v0.0.3 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/onflow/flow-go-sdk v1.9.3 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.9.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/assert v1.3.0 // indirect github.com/zeebo/blake3 v0.2.4 // indirect - golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.34.0 // indirect gonum.org/v1/gonum v0.16.0 // indirect - gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/onflow/cadence-standard-transactions => /Users/rayz/Desktop/Work/cadence-standard-transactions diff --git a/go.sum b/go.sum index 919f021c8..5e3da3482 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bits-and-blooms/bitset v1.24.0 h1:H4x4TuulnokZKvHLfzVRTHJfFfnHEeSYJizujEZvmAM= github.com/bits-and-blooms/bitset v1.24.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -72,8 +74,11 @@ github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEy github.com/dave/jennifer v1.5.0 h1:HmgPN93bVDpkQyYbqhCHj5QlgvUkvEOzMyEvKLgCRrg= github.com/dave/jennifer v1.5.0/go.mod h1:4MnyiFIlZS3l5tSDn8VnzE6ffAhYBMB2SZntBsZGUok= 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= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -199,12 +204,13 @@ github.com/k0kubun/pp/v3 v3.5.0 h1:iYNlYA5HJAJvkD4ibuf9c8y6SHM0QFhaBuCqm1zHp0w= github.com/k0kubun/pp/v3 v3.5.0/go.mod h1:5lzno5ZZeEeTV/Ky6vs3g6d1U3WarDrH8k240vMtGro= 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/klauspost/cpuid/v2 v2.2.0 h1:4ZexSFt8agMNzNisrsilL6RClWDC5YJnLHNIfTy4iuc= -github.com/klauspost/cpuid/v2 v2.2.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= +github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kodova/html-to-markdown v1.0.1 h1:MJxQAnqxtss3DaPnm72DRV65HZiMQZF3DUAfEaTg+14= github.com/kodova/html-to-markdown v1.0.1/go.mod h1:NhDrT7QdSrdpezFg/0EQx9zeobCHR5oAguzrKrC6mVU= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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= @@ -249,14 +255,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onflow/atree v0.12.0 h1:X7/UEPyCaaEQ1gCg11KDvfyEtEeQLhtRtxMHjAiH/Co= github.com/onflow/atree v0.12.0/go.mod h1:qdZcfLQwPirHcNpLiK+2t3KAo+SAb9Si6TqurE6pykE= github.com/onflow/crypto v0.25.3 h1:XQ3HtLsw8h1+pBN+NQ1JYM9mS2mVXTyg55OldaAIF7U= github.com/onflow/crypto v0.25.3/go.mod h1:+1igaXiK6Tjm9wQOBD1EGwW7bYWMUGKtwKJ/2QL/OWs= github.com/onflow/fixed-point v0.1.1 h1:j0jYZVO8VGyk1476alGudEg7XqCkeTVxb5ElRJRKS90= github.com/onflow/fixed-point v0.1.1/go.mod h1:gJdoHqKtToKdOZbvryJvDZfcpzC7d2fyWuo3ZmLtcGY= +github.com/onflow/flow-go-sdk v1.9.3 h1:VaJaZUJdcjdBBdRV0GmzzCBzgt9EUCJfqnVffdwaY0w= +github.com/onflow/flow-go-sdk v1.9.3/go.mod h1:HJRNJAMN+EkrdvJHB4cek2SwMFF5g66bKu071kZ1rIE= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -264,8 +270,9 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= -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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -273,8 +280,9 @@ 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/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= @@ -287,6 +295,8 @@ github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -367,8 +377,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -519,7 +529,6 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -715,8 +724,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -737,6 +746,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From 7343621ff3f0fb1fc4f2e5f81d6d2af9a0b0056e Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Thu, 20 Nov 2025 15:38:49 -0500 Subject: [PATCH 02/14] Add support for account setup, native functions, contracts in boilerplate. --- bbq/vm/test/transactions_test.go | 318 ++++++++++++++++++++++++++++--- 1 file changed, 288 insertions(+), 30 deletions(-) diff --git a/bbq/vm/test/transactions_test.go b/bbq/vm/test/transactions_test.go index 3e0b10873..bd186fb83 100644 --- a/bbq/vm/test/transactions_test.go +++ b/bbq/vm/test/transactions_test.go @@ -23,12 +23,18 @@ import ( "testing" "github.com/onflow/cadence-standard-transactions/transactions" + "github.com/onflow/cadence/activations" + "github.com/onflow/cadence/bbq" + "github.com/onflow/cadence/bbq/commons" + "github.com/onflow/cadence/bbq/compiler" . "github.com/onflow/cadence/bbq/test_utils" "github.com/onflow/cadence/bbq/vm" "github.com/onflow/cadence/common" "github.com/onflow/cadence/interpreter" + "github.com/onflow/cadence/sema" "github.com/onflow/cadence/stdlib" . "github.com/onflow/cadence/test_utils/interpreter_utils" + . "github.com/onflow/cadence/test_utils/runtime_utils" . "github.com/onflow/cadence/test_utils/sema_utils" "github.com/stretchr/testify/require" ) @@ -50,9 +56,7 @@ func createTransaction(name string, imports string, prepare string) Transaction transaction(){ prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { - var f: fun(): Void = fun(){} - f = fun() { %s } - f() + %s } }`, name, @@ -64,67 +68,321 @@ func createTransaction(name string, imports string, prepare string) Transaction func init() { testTransactions = []Transaction{ - createTransaction("EmptyLoopTransaction", "", transactions.EmptyLoopTransaction(5000).GetPrepareBlock()), + createTransaction("EmptyLoop", "", transactions.EmptyLoopTransaction(6000).GetPrepareBlock()), + createTransaction("AssertTrue", "", transactions.AssertTrueTransaction(3000).GetPrepareBlock()), + createTransaction("GetSignerAddress", "", transactions.GetSignerAddressTransaction(4000).GetPrepareBlock()), + createTransaction("GetSignerPublicAccount", "", transactions.GetSignerPublicAccountTransaction(3000).GetPrepareBlock()), + createTransaction("GetSignerAccountBalance", "", transactions.GetSignerAccountBalanceTransaction(30).GetPrepareBlock()), + createTransaction("GetSignerAccountAvailableBalance", "", transactions.GetSignerAccountAvailableBalanceTransaction(30).GetPrepareBlock()), + createTransaction("GetSignerAccountStorageUsed", "", transactions.GetSignerAccountStorageUsedTransaction(700).GetPrepareBlock()), + createTransaction("GetSignerAccountStorageCapacity", "", transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock()), + createTransaction("BorrowSignerAccountFlowTokenVault", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.BorrowSignerAccountFlowTokenVaultTransaction(700).GetPrepareBlock()), } } func BenchmarkTransactions(b *testing.B) { + // create addresses + contractsAddress := common.MustBytesToAddress([]byte{0x1}) + senderAddress := common.MustBytesToAddress([]byte{0x2}) + + locationHandler := newSingleAddressOrStringLocationHandler(b, contractsAddress) + + // make contracts available + compiledPrograms := CompiledPrograms{} + + burnerLocation := common.NewAddressLocation(nil, contractsAddress, "Burner") + viewResolverLocation := common.NewAddressLocation(nil, contractsAddress, "ViewResolver") + fungibleTokenLocation := common.NewAddressLocation(nil, contractsAddress, "FungibleToken") + metadataViewsLocation := common.NewAddressLocation(nil, contractsAddress, "MetadataViews") + fungibleTokenMetadataViewsLocation := common.NewAddressLocation(nil, contractsAddress, "FungibleTokenMetadataViews") + nonFungibleTokenLocation := common.NewAddressLocation(nil, contractsAddress, "NonFungibleToken") + flowTokenLocation := common.NewAddressLocation(nil, contractsAddress, "FlowToken") + + codes := map[common.Location][]byte{ + burnerLocation: []byte(realBurnerContract), + viewResolverLocation: []byte(realViewResolverContract), + fungibleTokenLocation: []byte(realFungibleTokenContract), + metadataViewsLocation: []byte(realMetadataViewsContract), + fungibleTokenMetadataViewsLocation: []byte(realFungibleTokenMetadataViewsContract), + nonFungibleTokenLocation: []byte(realNonFungibleTokenContract), + flowTokenLocation: []byte(realFlowContract), + } + + importHandler := func(location common.Location) *bbq.InstructionProgram { + imported, ok := compiledPrograms[location] + if !ok { + return nil + } + return imported.Program + } + + accountHandler := &testAccountHandler{ + emitEvent: func( + _ interpreter.ValueExportContext, + _ *sema.CompositeType, + _ []interpreter.Value, + ) { + // ignore + }, + getAccountBalance: func(address common.Address) (uint64, error) { + return 1000000000000000000, nil + }, + getAccountAvailableBalance: func(address common.Address) (uint64, error) { + return 1000000000000000000, nil + }, + getStorageUsed: func(address common.Address) (uint64, error) { + return 1000000000000000000, nil + }, + getStorageCapacity: func(address common.Address) (uint64, error) { + return 1000000000000000000, nil + }, + commitStorageTemporarily: func(context interpreter.ValueTransferContext) error { + return nil + }, + } + + // set up sema/compiler + semaConfig := &sema.Config{ + LocationHandler: locationHandler, + BaseValueActivationHandler: TestBaseValueActivation, + } + + compilerConfig := &compiler.Config{ + LocationHandler: locationHandler, + ImportHandler: importHandler, + ElaborationResolver: func(location common.Location) (*compiler.DesugaredElaboration, error) { + imported, ok := compiledPrograms[location] + if !ok { + return nil, fmt.Errorf("cannot find elaboration for %s", location) + } + return imported.DesugaredElaboration, nil + }, + BuiltinGlobalsProvider: func(_ common.Location) *activations.Activation[compiler.GlobalImport] { + activation := activations.NewActivation(nil, compiler.DefaultBuiltinGlobals()) + + activation.Set( + stdlib.AssertFunctionName, + compiler.NewGlobalImport(stdlib.AssertFunctionName), + ) + + activation.Set( + stdlib.GetAccountFunctionName, + compiler.NewGlobalImport(stdlib.GetAccountFunctionName), + ) + + activation.Set( + stdlib.PanicFunctionName, + compiler.NewGlobalImport(stdlib.PanicFunctionName), + ) + + return activation + }, + } + + // Parse and check contracts + + for _, location := range []common.Location{ + burnerLocation, + viewResolverLocation, + fungibleTokenLocation, + nonFungibleTokenLocation, + metadataViewsLocation, + fungibleTokenMetadataViewsLocation, + flowTokenLocation, + } { + _ = ParseCheckAndCompileCodeWithOptions( + b, + string(codes[location]), + location, + ParseCheckAndCompileOptions{ + ParseAndCheckOptions: &ParseAndCheckOptions{ + Location: location, + CheckerConfig: semaConfig, + }, + CompilerConfig: compilerConfig, + }, + compiledPrograms, + ) + } + + // set up VM vmConfig := vm.NewConfig(NewUnmeteredInMemoryStorage()) - // Set up account handler for creating signers vmConfig.AccountHandlerFunc = func( context interpreter.AccountCreationContext, address interpreter.AddressValue, ) interpreter.Value { - return stdlib.NewAccountValue(context, nil, address) + return stdlib.NewAccountValue(context, accountHandler, address) } - // Create a signer address - signerAddress := interpreter.NewUnmeteredAddressValueFromBytes([]byte{0x1}) + contractValues := make(map[common.Location]*interpreter.CompositeValue) + vmConfig.ContractValueHandler = func( + _ *vm.Context, + location common.Location, + ) *interpreter.CompositeValue { + return contractValues[location] + } - for _, transaction := range testTransactions { + vmConfig.ImportHandler = importHandler + + vmConfig.InjectedCompositeFieldsHandler = func( + context interpreter.AccountCreationContext, + _ common.Location, + _ string, + _ common.CompositeKind, + ) map[string]interpreter.Value { + + accountRef := stdlib.NewAccountReferenceValue( + context, + accountHandler, + interpreter.NewAddressValue(nil, contractsAddress), + interpreter.FullyEntitledAccountAccess, + ) + + return map[string]interpreter.Value{ + sema.ContractAccountFieldName: accountRef, + } + } + vmConfig.BuiltinGlobalsProvider = func(_ common.Location) *activations.Activation[vm.Variable] { + activation := activations.NewActivation(nil, vm.DefaultBuiltinGlobals()) + + panicVariable := &interpreter.SimpleVariable{} + panicVariable.InitializeWithValue(stdlib.VMPanicFunction.Value) + activation.Set( + stdlib.PanicFunctionName, + panicVariable, + ) + + assertVariable := &interpreter.SimpleVariable{} + assertVariable.InitializeWithValue(stdlib.VMAssertFunction.Value) + activation.Set( + stdlib.AssertFunctionName, + assertVariable, + ) + + getAccountVariable := &interpreter.SimpleVariable{} + getAccountVariable.InitializeWithValue(stdlib.NewVMGetAccountFunction(accountHandler).Value) + activation.Set( + stdlib.GetAccountFunctionName, + getAccountVariable, + ) + + for _, vmFunction := range []stdlib.VMFunction{ + stdlib.NewVMAccountCapabilitiesPublishFunction(accountHandler), + stdlib.NewVMAccountStorageCapabilitiesIssueFunction(accountHandler), + stdlib.NewVMAccountCapabilitiesGetFunction(accountHandler, true), + } { + variable := &interpreter.SimpleVariable{} + variable.InitializeWithValue(vmFunction.FunctionValue) + activation.Set( + commons.TypeQualifiedName( + vmFunction.BaseType, + vmFunction.FunctionValue.Name, + ), + variable, + ) + } + + return activation + } + + vmConfig = PrepareVMConfig(b, vmConfig, compiledPrograms) + + // Initialize contracts + for _, location := range []common.Location{ + metadataViewsLocation, + fungibleTokenMetadataViewsLocation, + flowTokenLocation, + } { + compiledProgram := compiledPrograms[location] + _, contractValue := initializeContract( + b, + location, + compiledProgram.Program, + vmConfig, + ) + + contractValues[location] = contractValue + } + + // all transactions use the same location, this prevents compiledPrograms from blowing up + nextTransactionLocation := NewTransactionLocationGenerator() + txLocation := nextTransactionLocation() + + for _, transaction := range testTransactions { b.Run(transaction.Name, func(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { b.StopTimer() - vmInstance, err := CompileAndPrepareToInvoke( + setupAccountProgram := ParseCheckAndCompileCodeWithOptions( b, - transaction.Body, - CompilerAndVMOptions{ - VMConfig: vmConfig, - ParseCheckAndCompileOptions: ParseCheckAndCompileOptions{ - ParseAndCheckOptions: &ParseAndCheckOptions{ - Location: common.TransactionLocation{}, - }, + ` + import "FungibleToken" + import "FlowToken" + + transaction { + prepare(signer: auth(Capabilities, Storage) &Account) { + if signer.storage.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault) == nil { + // Create a new flowToken Vault and put it in storage + signer.storage.save(<-FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>()), to: /storage/flowTokenVault) + } + } + } + `, + txLocation, + ParseCheckAndCompileOptions{ + ParseAndCheckOptions: &ParseAndCheckOptions{ + Location: txLocation, + CheckerConfig: semaConfig, }, + CompilerConfig: compilerConfig, }, + compiledPrograms, ) - require.NoError(b, err) - // Create signer for the transaction - signer := stdlib.NewAccountReferenceValue( - vmInstance.Context(), - nil, - signerAddress, + setupAccountVM := vm.NewVM(txLocation, setupAccountProgram, vmConfig) + + setupAccountAuthorizer := stdlib.NewAccountReferenceValue( + setupAccountVM.Context(), + accountHandler, + interpreter.NewAddressValue(nil, senderAddress), interpreter.FullyEntitledAccountAccess, ) - err = vmInstance.InvokeTransaction(nil, signer) + err := setupAccountVM.InvokeTransaction(nil, setupAccountAuthorizer) require.NoError(b, err) - // Rerun the same again using internal functions, to get the access to the transaction value. + program := ParseCheckAndCompileCodeWithOptions( + b, + transaction.Body, + txLocation, + ParseCheckAndCompileOptions{ + ParseAndCheckOptions: &ParseAndCheckOptions{ + Location: txLocation, + CheckerConfig: semaConfig, + }, + CompilerConfig: compilerConfig, + }, + compiledPrograms, + ) + + vmInstance := vm.NewVM(txLocation, program, vmConfig) - transaction, err := vmInstance.InvokeTransactionWrapper() - require.NoError(b, err) + authorizer := stdlib.NewAccountReferenceValue( + vmInstance.Context(), + accountHandler, + interpreter.NewAddressValue(nil, senderAddress), + interpreter.FullyEntitledAccountAccess, + ) b.StartTimer() - // Invoke 'prepare' with signer - err = vmInstance.InvokeTransactionPrepare(transaction, []vm.Value{signer}) + err = vmInstance.InvokeTransaction(nil, authorizer) b.StopTimer() require.NoError(b, err) + b.StartTimer() } }) } From 0ce7dcddf2e060597020cbd257d86bbb4c53bb81 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Fri, 21 Nov 2025 16:33:03 -0500 Subject: [PATCH 03/14] Add more transactions. --- ...ons_test.go => bench_transactions_test.go} | 220 ++++++++++++++---- bbq/vm/test/utils.go | 9 + stdlib/account.go | 8 +- stdlib/builtin.go | 4 +- 4 files changed, 194 insertions(+), 47 deletions(-) rename bbq/vm/test/{transactions_test.go => bench_transactions_test.go} (63%) diff --git a/bbq/vm/test/transactions_test.go b/bbq/vm/test/bench_transactions_test.go similarity index 63% rename from bbq/vm/test/transactions_test.go rename to bbq/vm/test/bench_transactions_test.go index bd186fb83..7734da8a3 100644 --- a/bbq/vm/test/transactions_test.go +++ b/bbq/vm/test/bench_transactions_test.go @@ -39,6 +39,12 @@ import ( "github.com/stretchr/testify/require" ) +type testRandomGenerator struct{} + +func (*testRandomGenerator) ReadRandom([]byte) error { + return nil +} + type Transaction struct { Name string Body string @@ -77,6 +83,14 @@ func init() { createTransaction("GetSignerAccountStorageUsed", "", transactions.GetSignerAccountStorageUsedTransaction(700).GetPrepareBlock()), createTransaction("GetSignerAccountStorageCapacity", "", transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock()), createTransaction("BorrowSignerAccountFlowTokenVault", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.BorrowSignerAccountFlowTokenVaultTransaction(700).GetPrepareBlock()), + createTransaction("BorrowSignerAccountFungibleTokenReceiver", "import \"FungibleToken\"", transactions.BorrowSignerAccountFungibleTokenReceiverTransaction(400).GetPrepareBlock()), + createTransaction("TransferTokensToSelf", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.TransferTokensToSelfTransaction(30).GetPrepareBlock()), + createTransaction("CreateNewAccount", "", transactions.CreateNewAccountTransaction(10).GetPrepareBlock()), + createTransaction("CreateNewAccountWithContract", "", transactions.CreateNewAccountWithContractTransaction(10).GetPrepareBlock()), + createTransaction("DecodeHex", "", transactions.DecodeHexTransaction(900).GetPrepareBlock()), + createTransaction("RevertibleRandomNumber", "", transactions.RevertibleRandomTransaction(2000).GetPrepareBlock()), + createTransaction("NumberToStringConversion", "", transactions.NumberToStringConversionTransaction(3000).GetPrepareBlock()), + createTransaction("ConcatenateString", "", transactions.ConcatenateStringTransaction(2000).GetPrepareBlock()), } } @@ -139,12 +153,50 @@ func BenchmarkTransactions(b *testing.B) { commitStorageTemporarily: func(context interpreter.ValueTransferContext) error { return nil }, + createAccount: func(payer common.Address) (common.Address, error) { + return common.Address{}, nil + }, + getAccountContractCode: func(location common.AddressLocation) ([]byte, error) { + return nil, nil + }, + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { + return nil + }, + recordContractUpdate: func(location common.AddressLocation, value *interpreter.CompositeValue) { + // NO-OP + }, + contractUpdateRecorded: func(location common.AddressLocation) bool { + return false + }, + parseAndCheckProgram: func(code []byte, location common.Location, getAndSetProgram bool) (*interpreter.Program, error) { + res, err := ParseAndCheck(b, string(code)) + require.NoError(b, err) + return &interpreter.Program{ + Program: res.Program, + Elaboration: res.Elaboration, + }, nil + }, + loadContractValue: func(location common.AddressLocation, program *interpreter.Program, name string, invocation stdlib.DeployedContractConstructorInvocation) (*interpreter.CompositeValue, error) { + return nil, nil + }, } + vmRevertibleRandomFunction := stdlib.NewVMRevertibleRandomFunction(&testRandomGenerator{}) + accountConstructor := stdlib.NewVMAccountConstructor(accountHandler) + // set up sema/compiler semaConfig := &sema.Config{ - LocationHandler: locationHandler, - BaseValueActivationHandler: TestBaseValueActivation, + LocationHandler: locationHandler, + BaseValueActivationHandler: func(_ common.Location) *sema.VariableActivation { + // Only need to make the checker happy + activation := sema.NewVariableActivation(sema.BaseValueActivation) + activation.DeclareValue(stdlib.VMPanicFunction) + activation.DeclareValue(stdlib.VMAssertFunction) + activation.DeclareValue(stdlib.NewVMGetAccountFunction(nil)) + activation.DeclareValue(vmRevertibleRandomFunction) + activation.DeclareValue(accountConstructor) + return activation + }, } compilerConfig := &compiler.Config{ @@ -175,6 +227,16 @@ func BenchmarkTransactions(b *testing.B) { compiler.NewGlobalImport(stdlib.PanicFunctionName), ) + activation.Set( + vmRevertibleRandomFunction.Name, + compiler.NewGlobalImport(vmRevertibleRandomFunction.Name), + ) + + activation.Set( + accountConstructor.Name, + compiler.NewGlobalImport(accountConstructor.Name), + ) + return activation }, } @@ -208,6 +270,32 @@ func BenchmarkTransactions(b *testing.B) { // set up VM vmConfig := vm.NewConfig(NewUnmeteredInMemoryStorage()) + vmConfig.CapabilityBorrowHandler = func( + context interpreter.BorrowCapabilityControllerContext, + address interpreter.AddressValue, + capabilityID interpreter.UInt64Value, + wantedBorrowType *sema.ReferenceType, + capabilityBorrowType *sema.ReferenceType, + ) interpreter.ReferenceValue { + return stdlib.BorrowCapabilityController( + context, + address, + capabilityID, + wantedBorrowType, + capabilityBorrowType, + accountHandler, + ) + } + + vmConfig.OnEventEmitted = func( + _ interpreter.ValueExportContext, + _ *sema.CompositeType, + _ []interpreter.Value, + ) error { + // NO-OP + return nil + } + vmConfig.AccountHandlerFunc = func( context interpreter.AccountCreationContext, address interpreter.AddressValue, @@ -272,6 +360,7 @@ func BenchmarkTransactions(b *testing.B) { stdlib.NewVMAccountCapabilitiesPublishFunction(accountHandler), stdlib.NewVMAccountStorageCapabilitiesIssueFunction(accountHandler), stdlib.NewVMAccountCapabilitiesGetFunction(accountHandler, true), + stdlib.NewVMAccountContractsChangeFunction(accountHandler, false), } { variable := &interpreter.SimpleVariable{} variable.InitializeWithValue(vmFunction.FunctionValue) @@ -284,6 +373,18 @@ func BenchmarkTransactions(b *testing.B) { ) } + for _, nativeFunction := range []stdlib.StandardLibraryValue{ + vmRevertibleRandomFunction, + accountConstructor, + } { + variable := &interpreter.SimpleVariable{} + variable.InitializeWithValue(nativeFunction.Value) + activation.Set( + nativeFunction.Name, + variable, + ) + } + return activation } @@ -310,48 +411,85 @@ func BenchmarkTransactions(b *testing.B) { nextTransactionLocation := NewTransactionLocationGenerator() txLocation := nextTransactionLocation() - for _, transaction := range testTransactions { - b.Run(transaction.Name, func(b *testing.B) { - for b.Loop() { - b.StopTimer() + // setup account, mint tokens + setupAccountProgram := ParseCheckAndCompileCodeWithOptions( + b, + realFlowTokenSetupAccountTransaction, + txLocation, + ParseCheckAndCompileOptions{ + ParseAndCheckOptions: &ParseAndCheckOptions{ + Location: txLocation, + CheckerConfig: semaConfig, + }, + CompilerConfig: compilerConfig, + }, + compiledPrograms, + ) + + setupAccountVM := vm.NewVM(txLocation, setupAccountProgram, vmConfig) + + setupAccountAuthorizer := stdlib.NewAccountReferenceValue( + setupAccountVM.Context(), + accountHandler, + interpreter.NewAddressValue(nil, senderAddress), + interpreter.FullyEntitledAccountAccess, + ) + + err := setupAccountVM.InvokeTransaction(nil, setupAccountAuthorizer) + require.NoError(b, err) + + txLocation = nextTransactionLocation() + + mintTokensTxProgram := ParseCheckAndCompileCodeWithOptions( + b, + realFlowTokenMintTokensTransaction, + txLocation, + ParseCheckAndCompileOptions{ + ParseAndCheckOptions: &ParseAndCheckOptions{ + Location: txLocation, + CheckerConfig: semaConfig, + }, + CompilerConfig: compilerConfig, + }, + compiledPrograms, + ) - setupAccountProgram := ParseCheckAndCompileCodeWithOptions( - b, - ` - import "FungibleToken" - import "FlowToken" - - transaction { - prepare(signer: auth(Capabilities, Storage) &Account) { - if signer.storage.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault) == nil { - // Create a new flowToken Vault and put it in storage - signer.storage.save(<-FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>()), to: /storage/flowTokenVault) - } - } - } - `, - txLocation, - ParseCheckAndCompileOptions{ - ParseAndCheckOptions: &ParseAndCheckOptions{ - Location: txLocation, - CheckerConfig: semaConfig, - }, - CompilerConfig: compilerConfig, - }, - compiledPrograms, - ) + mintTxVM := vm.NewVM(txLocation, mintTokensTxProgram, vmConfig) - setupAccountVM := vm.NewVM(txLocation, setupAccountProgram, vmConfig) + total := uint64(1000000) * sema.Fix64Factor - setupAccountAuthorizer := stdlib.NewAccountReferenceValue( - setupAccountVM.Context(), - accountHandler, - interpreter.NewAddressValue(nil, senderAddress), - interpreter.FullyEntitledAccountAccess, - ) + mintTxArgs := []vm.Value{ + interpreter.AddressValue(senderAddress), + interpreter.NewUnmeteredUFix64Value(total), + } - err := setupAccountVM.InvokeTransaction(nil, setupAccountAuthorizer) - require.NoError(b, err) + // Use the same authorizations as the one defined in the transaction. + semaAuthorization := sema.NewEntitlementSetAccess( + []*sema.EntitlementType{ + sema.BorrowValueType, + }, + sema.Conjunction, + ) + authorization := interpreter.ConvertSemaAccessToStaticAuthorization(nil, semaAuthorization) + + mintTxAuthorizer := stdlib.NewAccountReferenceValue( + mintTxVM.Context(), + accountHandler, + interpreter.AddressValue(contractsAddress), + authorization, + ) + + err = mintTxVM.InvokeTransaction(mintTxArgs, mintTxAuthorizer) + require.NoError(b, err) + require.Equal(b, 0, mintTxVM.StackSize()) + + // all benchmark transactions use the same location, this prevents compiledPrograms from blowing up + txLocation = nextTransactionLocation() + + for _, transaction := range testTransactions { + b.Run(transaction.Name, func(b *testing.B) { + for b.Loop() { + b.StopTimer() program := ParseCheckAndCompileCodeWithOptions( b, @@ -378,7 +516,7 @@ func BenchmarkTransactions(b *testing.B) { b.StartTimer() - err = vmInstance.InvokeTransaction(nil, authorizer) + err := vmInstance.InvokeTransaction(nil, authorizer) b.StopTimer() require.NoError(b, err) diff --git a/bbq/vm/test/utils.go b/bbq/vm/test/utils.go index 098e48e7a..8975571a5 100644 --- a/bbq/vm/test/utils.go +++ b/bbq/vm/test/utils.go @@ -106,9 +106,18 @@ type testAccountHandler struct { removeAccountContractCode func(location common.AddressLocation) error recordContractRemoval func(location common.AddressLocation) getAccountContractNames func(address common.Address) ([]string, error) + createAccount func(payer common.Address) (common.Address, error) } var _ stdlib.AccountHandler = &testAccountHandler{} +var _ stdlib.AccountCreator = &testAccountHandler{} + +func (t *testAccountHandler) CreateAccount(payer common.Address) (common.Address, error) { + if t.createAccount == nil { + panic(errors.NewUnexpectedError("unexpected call to CreateAccount")) + } + return t.createAccount(payer) +} func (t *testAccountHandler) GenerateAccountID(address common.Address) (uint64, error) { if t.generateAccountID == nil { diff --git a/stdlib/account.go b/stdlib/account.go index 34269034b..d7659ab3e 100644 --- a/stdlib/account.go +++ b/stdlib/account.go @@ -362,13 +362,13 @@ func newAccountContractsValue( return interpreter.NewAccountContractsValue( context, addressValue, - newInterpreterAccountContractsChangeFunction( + NewInterpreterAccountContractsChangeFunction( context, handler, addressValue, false, ), - newInterpreterAccountContractsChangeFunction( + NewInterpreterAccountContractsChangeFunction( context, handler, addressValue, @@ -1742,7 +1742,7 @@ func nativeAccountContractsChangeFunction( // newInterpreterAccountContractsChangeFunction called when e.g. // - adding: `Account.contracts.add(name: "Foo", code: [...])` (isUpdate = false) // - updating: `Account.contracts.update(name: "Foo", code: [...])` (isUpdate = true) -func newInterpreterAccountContractsChangeFunction( +func NewInterpreterAccountContractsChangeFunction( context interpreter.FunctionCreationContext, handler AccountContractAdditionAndNamesHandler, addressValue interpreter.AddressValue, @@ -1764,7 +1764,7 @@ func newInterpreterAccountContractsChangeFunction( } } -func newVMAccountContractsChangeFunction( +func NewVMAccountContractsChangeFunction( handler AccountContractAdditionAndNamesHandler, isUpdate bool, ) VMFunction { diff --git a/stdlib/builtin.go b/stdlib/builtin.go index 76d39f9ef..3c29acb83 100644 --- a/stdlib/builtin.go +++ b/stdlib/builtin.go @@ -115,8 +115,8 @@ func VMFunctions(handler StandardLibraryHandler) []VMFunction { NewVMAccountContractsGetFunction(handler), NewVMAccountContractsBorrowFunction(handler), - newVMAccountContractsChangeFunction(handler, true), - newVMAccountContractsChangeFunction(handler, false), + NewVMAccountContractsChangeFunction(handler, true), + NewVMAccountContractsChangeFunction(handler, false), newVMAccountContractsTryUpdateFunction(handler), newVMAccountContractsRemoveFunction(handler), From 3b22660c52d862c10e00fb4c955deeb3ab63698f Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Fri, 21 Nov 2025 18:10:41 -0500 Subject: [PATCH 04/14] Add more transactions. --- bbq/vm/test/bench_transactions_test.go | 120 ++++++++++++++++++------- go.mod | 2 +- 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/bbq/vm/test/bench_transactions_test.go b/bbq/vm/test/bench_transactions_test.go index 7734da8a3..4b7f3ef3b 100644 --- a/bbq/vm/test/bench_transactions_test.go +++ b/bbq/vm/test/bench_transactions_test.go @@ -20,6 +20,7 @@ package test import ( "fmt" + "strings" "testing" "github.com/onflow/cadence-standard-transactions/transactions" @@ -46,13 +47,14 @@ func (*testRandomGenerator) ReadRandom([]byte) error { } type Transaction struct { - Name string - Body string + Name string + Body string + Setup string } var testTransactions []Transaction -func createTransaction(name string, imports string, prepare string) Transaction { +func createTransaction(name string, imports string, prepare string, setup string) Transaction { return Transaction{ Name: name, Body: fmt.Sprintf( @@ -69,32 +71,71 @@ func createTransaction(name string, imports string, prepare string) Transaction imports, prepare, ), + Setup: fmt.Sprintf( + ` + transaction(){ + prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { + %s + } + }`, + setup, + ), + } +} + +func stringOfLen(length uint64) string { + someString := make([]byte, length) + for i := 0; i < len(someString); i++ { + someString[i] = 'x' } + return string(someString) +} + +func stringArrayOfLen(arrayLen uint64, stringLen uint64) string { + builder := strings.Builder{} + builder.WriteRune('[') + for i := uint64(0); i < arrayLen; i++ { + if i > 0 { + builder.WriteRune(',') + } + builder.WriteRune('"') + builder.WriteString(stringOfLen(stringLen)) + builder.WriteRune('"') + } + builder.WriteRune(']') + return builder.String() } func init() { testTransactions = []Transaction{ - createTransaction("EmptyLoop", "", transactions.EmptyLoopTransaction(6000).GetPrepareBlock()), - createTransaction("AssertTrue", "", transactions.AssertTrueTransaction(3000).GetPrepareBlock()), - createTransaction("GetSignerAddress", "", transactions.GetSignerAddressTransaction(4000).GetPrepareBlock()), - createTransaction("GetSignerPublicAccount", "", transactions.GetSignerPublicAccountTransaction(3000).GetPrepareBlock()), - createTransaction("GetSignerAccountBalance", "", transactions.GetSignerAccountBalanceTransaction(30).GetPrepareBlock()), - createTransaction("GetSignerAccountAvailableBalance", "", transactions.GetSignerAccountAvailableBalanceTransaction(30).GetPrepareBlock()), - createTransaction("GetSignerAccountStorageUsed", "", transactions.GetSignerAccountStorageUsedTransaction(700).GetPrepareBlock()), - createTransaction("GetSignerAccountStorageCapacity", "", transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock()), - createTransaction("BorrowSignerAccountFlowTokenVault", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.BorrowSignerAccountFlowTokenVaultTransaction(700).GetPrepareBlock()), - createTransaction("BorrowSignerAccountFungibleTokenReceiver", "import \"FungibleToken\"", transactions.BorrowSignerAccountFungibleTokenReceiverTransaction(400).GetPrepareBlock()), - createTransaction("TransferTokensToSelf", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.TransferTokensToSelfTransaction(30).GetPrepareBlock()), - createTransaction("CreateNewAccount", "", transactions.CreateNewAccountTransaction(10).GetPrepareBlock()), - createTransaction("CreateNewAccountWithContract", "", transactions.CreateNewAccountWithContractTransaction(10).GetPrepareBlock()), - createTransaction("DecodeHex", "", transactions.DecodeHexTransaction(900).GetPrepareBlock()), - createTransaction("RevertibleRandomNumber", "", transactions.RevertibleRandomTransaction(2000).GetPrepareBlock()), - createTransaction("NumberToStringConversion", "", transactions.NumberToStringConversionTransaction(3000).GetPrepareBlock()), - createTransaction("ConcatenateString", "", transactions.ConcatenateStringTransaction(2000).GetPrepareBlock()), + createTransaction( + "EmptyLoop", + "", + transactions.EmptyLoopTransaction(6000).GetPrepareBlock(), + "", + ), + createTransaction("AssertTrue", "", transactions.AssertTrueTransaction(3000).GetPrepareBlock(), ""), + createTransaction("GetSignerAddress", "", transactions.GetSignerAddressTransaction(4000).GetPrepareBlock(), ""), + createTransaction("GetSignerPublicAccount", "", transactions.GetSignerPublicAccountTransaction(3000).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountBalance", "", transactions.GetSignerAccountBalanceTransaction(30).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountAvailableBalance", "", transactions.GetSignerAccountAvailableBalanceTransaction(30).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountStorageUsed", "", transactions.GetSignerAccountStorageUsedTransaction(700).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountStorageCapacity", "", transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock(), ""), + createTransaction("BorrowSignerAccountFlowTokenVault", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.BorrowSignerAccountFlowTokenVaultTransaction(700).GetPrepareBlock(), ""), + createTransaction("BorrowSignerAccountFungibleTokenReceiver", "import \"FungibleToken\"", transactions.BorrowSignerAccountFungibleTokenReceiverTransaction(400).GetPrepareBlock(), ""), + createTransaction("TransferTokensToSelf", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.TransferTokensToSelfTransaction(30).GetPrepareBlock(), ""), + createTransaction("CreateNewAccount", "", transactions.CreateNewAccountTransaction(10).GetPrepareBlock(), ""), + createTransaction("CreateNewAccountWithContract", "", transactions.CreateNewAccountWithContractTransaction(10).GetPrepareBlock(), ""), + createTransaction("DecodeHex", "", transactions.DecodeHexTransaction(900).GetPrepareBlock(), ""), + createTransaction("RevertibleRandomNumber", "", transactions.RevertibleRandomTransaction(2000).GetPrepareBlock(), ""), + createTransaction("NumberToStringConversion", "", transactions.NumberToStringConversionTransaction(3000).GetPrepareBlock(), ""), + createTransaction("ConcatenateString", "", transactions.ConcatenateStringTransaction(2000).GetPrepareBlock(), ""), + createTransaction("BorrowString", "", transactions.BorrowStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.BorrowStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), + createTransaction("CopyString", "", transactions.CopyStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.CopyStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), } } -func BenchmarkTransactions(b *testing.B) { +func BenchmarkTransactionsVM(b *testing.B) { // create addresses contractsAddress := common.MustBytesToAddress([]byte{0x1}) senderAddress := common.MustBytesToAddress([]byte{0x2}) @@ -407,7 +448,6 @@ func BenchmarkTransactions(b *testing.B) { contractValues[location] = contractValue } - // all transactions use the same location, this prevents compiledPrograms from blowing up nextTransactionLocation := NewTransactionLocationGenerator() txLocation := nextTransactionLocation() @@ -486,14 +526,21 @@ func BenchmarkTransactions(b *testing.B) { // all benchmark transactions use the same location, this prevents compiledPrograms from blowing up txLocation = nextTransactionLocation() + authorizer := stdlib.NewAccountReferenceValue( + mintTxVM.Context(), // ctx shouldn't matter + accountHandler, + interpreter.NewAddressValue(nil, senderAddress), + interpreter.FullyEntitledAccountAccess, + ) + for _, transaction := range testTransactions { b.Run(transaction.Name, func(b *testing.B) { for b.Loop() { b.StopTimer() - program := ParseCheckAndCompileCodeWithOptions( + setupProgram := ParseCheckAndCompileCodeWithOptions( b, - transaction.Body, + transaction.Setup, txLocation, ParseCheckAndCompileOptions{ ParseAndCheckOptions: &ParseAndCheckOptions{ @@ -504,19 +551,30 @@ func BenchmarkTransactions(b *testing.B) { }, compiledPrograms, ) + setupVM := vm.NewVM(txLocation, setupProgram, vmConfig) - vmInstance := vm.NewVM(txLocation, program, vmConfig) + err := setupVM.InvokeTransaction(nil, authorizer) + require.NoError(b, err) + require.Equal(b, 0, setupVM.StackSize()) - authorizer := stdlib.NewAccountReferenceValue( - vmInstance.Context(), - accountHandler, - interpreter.NewAddressValue(nil, senderAddress), - interpreter.FullyEntitledAccountAccess, + program := ParseCheckAndCompileCodeWithOptions( + b, + transaction.Body, + txLocation, + ParseCheckAndCompileOptions{ + ParseAndCheckOptions: &ParseAndCheckOptions{ + Location: txLocation, + CheckerConfig: semaConfig, + }, + CompilerConfig: compilerConfig, + }, + compiledPrograms, ) + vmInstance := vm.NewVM(txLocation, program, vmConfig) b.StartTimer() - err := vmInstance.InvokeTransaction(nil, authorizer) + err = vmInstance.InvokeTransaction(nil, authorizer) b.StopTimer() require.NoError(b, err) diff --git a/go.mod b/go.mod index 23d3ddc36..5243d1f44 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/leanovate/gopter v0.2.11 github.com/logrusorgru/aurora/v4 v4.0.0 github.com/onflow/atree v0.12.0 - github.com/onflow/cadence-standard-transactions v0.0.0-20251118182655-c31f418b74bc + github.com/onflow/cadence-standard-transactions v0.0.0-00010101000000-000000000000 github.com/onflow/crypto v0.25.3 github.com/onflow/fixed-point v0.1.1 github.com/rivo/uniseg v0.4.7 From cc94149efac1b9d1f1c31110e042ec3fc2eb440a Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Fri, 21 Nov 2025 20:18:52 -0500 Subject: [PATCH 05/14] Add runtime version of transaction benchmarks. --- runtime/bench_standard_transactions_test.go | 329 ++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 runtime/bench_standard_transactions_test.go diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go new file mode 100644 index 000000000..95c80a6b4 --- /dev/null +++ b/runtime/bench_standard_transactions_test.go @@ -0,0 +1,329 @@ +/* + * Cadence - The resource-oriented smart contract programming language + * + * Copyright Flow Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package runtime_test + +import ( + "encoding/binary" + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/onflow/cadence" + "github.com/onflow/cadence-standard-transactions/transactions" + "github.com/onflow/cadence/common" + "github.com/onflow/cadence/encoding/json" + "github.com/onflow/cadence/interpreter" + . "github.com/onflow/cadence/runtime" + . "github.com/onflow/cadence/test_utils/runtime_utils" +) + +type Transaction struct { + Name string + Body string + Setup string +} + +var testTransactions []Transaction + +func createTransaction(name string, imports string, prepare string, setup string) Transaction { + return Transaction{ + Name: name, + Body: fmt.Sprintf( + ` + // %s + %s + + transaction(){ + prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { + %s + } + }`, + name, + imports, + prepare, + ), + Setup: fmt.Sprintf( + ` + transaction(){ + prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { + %s + } + }`, + setup, + ), + } +} + +func stringOfLen(length uint64) string { + someString := make([]byte, length) + for i := 0; i < len(someString); i++ { + someString[i] = 'x' + } + return string(someString) +} + +func stringArrayOfLen(arrayLen uint64, stringLen uint64) string { + builder := strings.Builder{} + builder.WriteRune('[') + for i := uint64(0); i < arrayLen; i++ { + if i > 0 { + builder.WriteRune(',') + } + builder.WriteRune('"') + builder.WriteString(stringOfLen(stringLen)) + builder.WriteRune('"') + } + builder.WriteRune(']') + return builder.String() +} + +func init() { + testTransactions = []Transaction{ + createTransaction( + "EmptyLoop", + "", + transactions.EmptyLoopTransaction(6000).GetPrepareBlock(), + "", + ), + createTransaction("AssertTrue", "", transactions.AssertTrueTransaction(3000).GetPrepareBlock(), ""), + createTransaction("GetSignerAddress", "", transactions.GetSignerAddressTransaction(4000).GetPrepareBlock(), ""), + createTransaction("GetSignerPublicAccount", "", transactions.GetSignerPublicAccountTransaction(3000).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountBalance", "", transactions.GetSignerAccountBalanceTransaction(30).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountAvailableBalance", "", transactions.GetSignerAccountAvailableBalanceTransaction(30).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountStorageUsed", "", transactions.GetSignerAccountStorageUsedTransaction(700).GetPrepareBlock(), ""), + createTransaction("GetSignerAccountStorageCapacity", "", transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock(), ""), + createTransaction("BorrowSignerAccountFlowTokenVault", "import FungibleToken from 0x1\nimport FlowToken from 0x1", transactions.BorrowSignerAccountFlowTokenVaultTransaction(700).GetPrepareBlock(), ""), + createTransaction("BorrowSignerAccountFungibleTokenReceiver", "import FungibleToken from 0x1\nimport FlowToken from 0x1", transactions.BorrowSignerAccountFungibleTokenReceiverTransaction(400).GetPrepareBlock(), ""), + createTransaction("TransferTokensToSelf", "import FungibleToken from 0x1\nimport FlowToken from 0x1", transactions.TransferTokensToSelfTransaction(30).GetPrepareBlock(), ""), + createTransaction("CreateNewAccount", "", transactions.CreateNewAccountTransaction(10).GetPrepareBlock(), ""), + createTransaction("CreateNewAccountWithContract", "", transactions.CreateNewAccountWithContractTransaction(10).GetPrepareBlock(), ""), + createTransaction("DecodeHex", "", transactions.DecodeHexTransaction(900).GetPrepareBlock(), ""), + createTransaction("RevertibleRandomNumber", "", transactions.RevertibleRandomTransaction(2000).GetPrepareBlock(), ""), + createTransaction("NumberToStringConversion", "", transactions.NumberToStringConversionTransaction(3000).GetPrepareBlock(), ""), + createTransaction("ConcatenateString", "", transactions.ConcatenateStringTransaction(2000).GetPrepareBlock(), ""), + createTransaction("BorrowString", "", transactions.BorrowStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.BorrowStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), + createTransaction("CopyString", "", transactions.CopyStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.CopyStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), + } +} + +func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { + runtime := NewTestRuntime() + + contractsAddress := common.MustBytesToAddress([]byte{0x1}) + senderAddress := common.MustBytesToAddress([]byte{0x2}) + receiverAddress := common.MustBytesToAddress([]byte{0x3}) + + accountCodes := map[common.Location][]byte{} + + var events []cadence.Event + + signerAccount := contractsAddress + + // Counter for generating unique account addresses + // Use uint64 to avoid overflow issues with large iteration counts + var accountCounter uint64 = 4 + + runtimeInterface := &TestRuntimeInterface{ + OnGetCode: func(location common.Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]common.Address, error) { + return []common.Address{signerAccount}, nil + }, + OnResolveLocation: NewSingleIdentifierLocationResolver(b), + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (value cadence.Value, err error) { + return json.Decode(nil, b) + }, + OnGetAccountBalance: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetAccountAvailableBalance: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetStorageUsed: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetStorageCapacity: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnCreateAccount: func(payer Address) (address Address, err error) { + // Generate unique address from counter using binary encoding + accountCounter++ + addressBytes := make([]byte, 8) + binary.BigEndian.PutUint64(addressBytes, accountCounter) + result := interpreter.NewUnmeteredAddressValueFromBytes(addressBytes) + return result.ToAddress(), nil + }, + } + + var environment Environment + if useVM { + environment = NewBaseVMEnvironment(Config{}) + } else { + environment = NewBaseInterpreterEnvironment(Config{}) + } + + nextTransactionLocation := NewTransactionLocationGenerator() + + // Deploy Fungible Token contract + + err := runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction( + "FungibleToken", + []byte(modifiedFungibleTokenContractInterface), + ), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Deploy Flow Token contract + + err = runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction("FlowToken", []byte(modifiedFlowContract)), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Setup both user accounts for Flow Token + + for _, address := range []common.Address{ + senderAddress, + receiverAddress, + } { + + signerAccount = address + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(realSetupFlowTokenAccountTransaction), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + } + + // Mint 1000 FLOW to sender + + mintAmount, err := cadence.NewUFix64("100000000000.0") + require.NoError(b, err) + + signerAccount = contractsAddress + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(realMintFlowTokenTransaction), + Arguments: encodeArgs([]cadence.Value{ + cadence.Address(senderAddress), + mintAmount, + }), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Set signer account to sender for benchmark transactions + signerAccount = senderAddress + + // all benchmark transactions reuse the same location + for _, transaction := range testTransactions { + b.Run(transaction.Name, func(b *testing.B) { + for b.Loop() { + b.StopTimer() + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(transaction.Setup), + Arguments: nil, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + b.StartTimer() + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(transaction.Body), + Arguments: nil, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + + b.StopTimer() + require.NoError(b, err) + b.StartTimer() + } + }) + } +} + +func BenchmarkRuntimeTransactionsInterpreter(b *testing.B) { + benchmarkRuntimeTransactions(b, false) +} + +func BenchmarkRuntimeTransactionsVM(b *testing.B) { + benchmarkRuntimeTransactions(b, true) +} From 2186e9fb8fae0f9fca3960392d7d329e67f33943 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Mon, 24 Nov 2025 17:33:58 -0500 Subject: [PATCH 06/14] Add supportable simple transactions. --- go.mod | 14 +- go.sum | 24 +- runtime/bench_standard_transactions_test.go | 1015 ++++++++++++++++--- 3 files changed, 882 insertions(+), 171 deletions(-) diff --git a/go.mod b/go.mod index 5243d1f44..868966306 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/onflow/cadence-standard-transactions v0.0.0-00010101000000-000000000000 github.com/onflow/crypto v0.25.3 github.com/onflow/fixed-point v0.1.1 + github.com/onflow/flow-go-sdk v1.9.3 github.com/rivo/uniseg v0.4.7 github.com/schollz/progressbar/v3 v3.18.0 github.com/stretchr/testify v1.11.1 @@ -38,28 +39,33 @@ require ( require ( github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect github.com/fxamacker/circlehash v0.3.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/holiman/uint256 v1.3.2 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect - github.com/klauspost/cpuid/v2 v2.2.6 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-tty v0.0.3 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect - github.com/onflow/flow-go-sdk v1.9.3 // indirect + github.com/onflow/flow/protobuf/go/flow v0.4.18 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/assert v1.3.0 // indirect github.com/zeebo/blake3 v0.2.4 // indirect - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect + golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/term v0.34.0 // indirect gonum.org/v1/gonum v0.16.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5e3da3482..f6a0ac071 100644 --- a/go.sum +++ b/go.sum @@ -77,8 +77,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -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/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -86,6 +86,8 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.16.7 h1:qeM4TvbrWK0UC0tgkZ7NiRsmBGwsjqc64BHo20U59UQ= +github.com/ethereum/go-ethereum v1.16.7/go.mod h1:Fs6QebQbavneQTYcA39PEKv2+zIjX7rPUZ14DER46wk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fxamacker/cbor/v2 v2.9.1-0.20251019205732-39888e6be013 h1:jcwW+JBYGe3qgiPQ4deXaannYxVdxjMw57/dw+gcEfQ= @@ -129,6 +131,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -189,6 +193,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -204,8 +210,8 @@ github.com/k0kubun/pp/v3 v3.5.0 h1:iYNlYA5HJAJvkD4ibuf9c8y6SHM0QFhaBuCqm1zHp0w= github.com/k0kubun/pp/v3 v3.5.0/go.mod h1:5lzno5ZZeEeTV/Ky6vs3g6d1U3WarDrH8k240vMtGro= 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/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= +github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/kodova/html-to-markdown v1.0.1 h1:MJxQAnqxtss3DaPnm72DRV65HZiMQZF3DUAfEaTg+14= github.com/kodova/html-to-markdown v1.0.1/go.mod h1:NhDrT7QdSrdpezFg/0EQx9zeobCHR5oAguzrKrC6mVU= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -263,10 +269,14 @@ github.com/onflow/fixed-point v0.1.1 h1:j0jYZVO8VGyk1476alGudEg7XqCkeTVxb5ElRJRK github.com/onflow/fixed-point v0.1.1/go.mod h1:gJdoHqKtToKdOZbvryJvDZfcpzC7d2fyWuo3ZmLtcGY= github.com/onflow/flow-go-sdk v1.9.3 h1:VaJaZUJdcjdBBdRV0GmzzCBzgt9EUCJfqnVffdwaY0w= github.com/onflow/flow-go-sdk v1.9.3/go.mod h1:HJRNJAMN+EkrdvJHB4cek2SwMFF5g66bKu071kZ1rIE= +github.com/onflow/flow/protobuf/go/flow v0.4.18 h1:KOujA6lg9kTXCV6oK0eErD1rwRnM9taKZss3Szi+T3Q= +github.com/onflow/flow/protobuf/go/flow v0.4.18/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= @@ -377,8 +387,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -722,6 +732,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go index 95c80a6b4..16cc885f9 100644 --- a/runtime/bench_standard_transactions_test.go +++ b/runtime/bench_standard_transactions_test.go @@ -19,8 +19,11 @@ package runtime_test import ( + "crypto/rand" "encoding/binary" + "encoding/hex" "fmt" + "strconv" "strings" "testing" @@ -32,9 +35,184 @@ import ( "github.com/onflow/cadence/encoding/json" "github.com/onflow/cadence/interpreter" . "github.com/onflow/cadence/runtime" + "github.com/onflow/cadence/stdlib" . "github.com/onflow/cadence/test_utils/runtime_utils" + flowsdk "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go-sdk/crypto" ) +var realCryptoContract = ` +access(all) contract Crypto { + + access(all) + fun hash(_ data: [UInt8], algorithm: HashAlgorithm): [UInt8] { + return algorithm.hash(data) + } + + access(all) + fun hashWithTag(_ data: [UInt8], tag: String, algorithm: HashAlgorithm): [UInt8] { + return algorithm.hashWithTag(data, tag: tag) + } + + access(all) + struct KeyListEntry { + + access(all) + let keyIndex: Int + + access(all) + let publicKey: PublicKey + + access(all) + let hashAlgorithm: HashAlgorithm + + access(all) + let weight: UFix64 + + access(all) + let isRevoked: Bool + + init( + keyIndex: Int, + publicKey: PublicKey, + hashAlgorithm: HashAlgorithm, + weight: UFix64, + isRevoked: Bool + ) { + self.keyIndex = keyIndex + self.publicKey = publicKey + self.hashAlgorithm = hashAlgorithm + self.weight = weight + self.isRevoked = isRevoked + } + } + + access(all) + struct KeyList { + + access(self) + let entries: [KeyListEntry] + + init() { + self.entries = [] + } + + /// Adds a new key with the given weight + access(all) + fun add( + _ publicKey: PublicKey, + hashAlgorithm: HashAlgorithm, + weight: UFix64 + ): KeyListEntry { + + let keyIndex = self.entries.length + let entry = KeyListEntry( + keyIndex: keyIndex, + publicKey: publicKey, + hashAlgorithm: hashAlgorithm, + weight: weight, + isRevoked: false + ) + self.entries.append(entry) + return entry + } + + /// Returns the key at the given index, if it exists. + /// Revoked keys are always returned, but they have the isRevoked field set to true + access(all) + fun get(keyIndex: Int): KeyListEntry? { + if keyIndex >= self.entries.length { + return nil + } + + return self.entries[keyIndex] + } + + /// Marks the key at the given index revoked, but does not delete it + access(all) + fun revoke(keyIndex: Int) { + if keyIndex >= self.entries.length { + return + } + + let currentEntry = self.entries[keyIndex] + self.entries[keyIndex] = KeyListEntry( + keyIndex: currentEntry.keyIndex, + publicKey: currentEntry.publicKey, + hashAlgorithm: currentEntry.hashAlgorithm, + weight: currentEntry.weight, + isRevoked: true + ) + } + + /// Returns true if the given signatures are valid for the given signed data + access(all) + fun verify( + signatureSet: [KeyListSignature], + signedData: [UInt8], + domainSeparationTag: String + ): Bool { + + var validWeights: UFix64 = 0.0 + + let seenKeyIndices: {Int: Bool} = {} + + for signature in signatureSet { + + // Ensure the key index is valid + if signature.keyIndex >= self.entries.length { + return false + } + + // Ensure this key index has not already been seen + if seenKeyIndices[signature.keyIndex] ?? false { + return false + } + + // Record the key index was seen + seenKeyIndices[signature.keyIndex] = true + + // Get the actual key + let key = self.entries[signature.keyIndex] + + // Ensure the key is not revoked + if key.isRevoked { + return false + } + + // Ensure the signature is valid + if !key.publicKey.verify( + signature: signature.signature, + signedData: signedData, + domainSeparationTag: domainSeparationTag, + hashAlgorithm:key.hashAlgorithm + ) { + return false + } + + validWeights = validWeights + key.weight + } + + return validWeights >= 1.0 + } + } + + access(all) + struct KeyListSignature { + + access(all) + let keyIndex: Int + + access(all) + let signature: [UInt8] + + init(keyIndex: Int, signature: [UInt8]) { + self.keyIndex = keyIndex + self.signature = signature + } + } +}` + type Transaction struct { Name string Body string @@ -95,96 +273,480 @@ func stringArrayOfLen(arrayLen uint64, stringLen uint64) string { return builder.String() } +func stringDictOfLen(dictLen uint64, stringLen uint64) string { + builder := strings.Builder{} + builder.WriteRune('{') + for i := uint64(0); i < dictLen; i++ { + if i > 0 { + builder.WriteRune(',') + } + builder.WriteRune('"') + someString := make([]byte, stringLen) + for i := 0; i < len(someString); i++ { + someString[i] = 'x' + } + builder.WriteString(string(someString)) + builder.WriteString(strconv.Itoa(int(i))) + builder.WriteRune('"') + builder.WriteRune(':') + builder.WriteRune('"') + builder.WriteString(string(someString)) + builder.WriteRune('"') + } + builder.WriteRune('}') + return builder.String() +} + func init() { + // create key transactions + createKeyECDSAP256Transaction, err := transactions.CreateKeyECDSAP256Transaction(100) + if err != nil { + panic(err) + } + createKeyECDSAsecp256k1Transaction, err := transactions.CreateKeyECDSAsecp256k1Transaction(100) + if err != nil { + panic(err) + } + createKeyBLSBLS12381Transaction, err := transactions.CreateKeyBLSBLS12381Transaction(100) + if err != nil { + panic(err) + } + + // verify signature transaction + numKeys := uint64(15) + message := []byte("hello world") + + rawKeys := make([]string, numKeys) + signers := make([]crypto.Signer, numKeys) + signatures := make([]string, numKeys) + + for i := 0; i < int(numKeys); i++ { + seed := make([]byte, crypto.MinSeedLength) + _, err := rand.Read(seed) + if err != nil { + panic(fmt.Errorf("failed to generate seed: %w", err)) + } + + privateKey, err := crypto.GeneratePrivateKey(crypto.ECDSA_P256, seed) + if err != nil { + panic(fmt.Errorf("failed to generate private key: %w", err)) + } + rawKeys[i] = hex.EncodeToString(privateKey.PublicKey().Encode()) + sig, err := crypto.NewInMemorySigner(privateKey, crypto.SHA3_256) + if err != nil { + panic(fmt.Errorf("failed to generate signer: %w", err)) + } + signers[i] = sig + } + + for i := 0; i < int(numKeys); i++ { + sig, err := flowsdk.SignUserMessage(signers[i], message) + if err != nil { + panic(fmt.Errorf("failed to sign message: %w", err)) + } + signatures[i] = hex.EncodeToString(sig) + } + verifySignatureTransaction := transactions.VerifySignatureTransaction(numKeys, message, rawKeys, signatures) + + // bls + blsAggregateKeysTransaction, err := transactions.AggregateBLSAggregateKeysTransaction(42) + if err != nil { + panic(err) + } + + blsVerifyProofOfPossessionTransaction, err := transactions.BLSVerifyProofOfPossessionTransaction(8) + if err != nil { + panic(err) + } + testTransactions = []Transaction{ createTransaction( "EmptyLoop", "", - transactions.EmptyLoopTransaction(6000).GetPrepareBlock(), - "", - ), - createTransaction("AssertTrue", "", transactions.AssertTrueTransaction(3000).GetPrepareBlock(), ""), - createTransaction("GetSignerAddress", "", transactions.GetSignerAddressTransaction(4000).GetPrepareBlock(), ""), - createTransaction("GetSignerPublicAccount", "", transactions.GetSignerPublicAccountTransaction(3000).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountBalance", "", transactions.GetSignerAccountBalanceTransaction(30).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountAvailableBalance", "", transactions.GetSignerAccountAvailableBalanceTransaction(30).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountStorageUsed", "", transactions.GetSignerAccountStorageUsedTransaction(700).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountStorageCapacity", "", transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock(), ""), - createTransaction("BorrowSignerAccountFlowTokenVault", "import FungibleToken from 0x1\nimport FlowToken from 0x1", transactions.BorrowSignerAccountFlowTokenVaultTransaction(700).GetPrepareBlock(), ""), - createTransaction("BorrowSignerAccountFungibleTokenReceiver", "import FungibleToken from 0x1\nimport FlowToken from 0x1", transactions.BorrowSignerAccountFungibleTokenReceiverTransaction(400).GetPrepareBlock(), ""), - createTransaction("TransferTokensToSelf", "import FungibleToken from 0x1\nimport FlowToken from 0x1", transactions.TransferTokensToSelfTransaction(30).GetPrepareBlock(), ""), - createTransaction("CreateNewAccount", "", transactions.CreateNewAccountTransaction(10).GetPrepareBlock(), ""), - createTransaction("CreateNewAccountWithContract", "", transactions.CreateNewAccountWithContractTransaction(10).GetPrepareBlock(), ""), - createTransaction("DecodeHex", "", transactions.DecodeHexTransaction(900).GetPrepareBlock(), ""), - createTransaction("RevertibleRandomNumber", "", transactions.RevertibleRandomTransaction(2000).GetPrepareBlock(), ""), - createTransaction("NumberToStringConversion", "", transactions.NumberToStringConversionTransaction(3000).GetPrepareBlock(), ""), - createTransaction("ConcatenateString", "", transactions.ConcatenateStringTransaction(2000).GetPrepareBlock(), ""), - createTransaction("BorrowString", "", transactions.BorrowStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.BorrowStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), - createTransaction("CopyString", "", transactions.CopyStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.CopyStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), + transactions.EmptyLoopTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "AssertTrue", + "", + transactions.AssertTrueTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "GetSignerAddress", + "", + transactions.GetSignerAddressTransaction(50).GetPrepareBlock(), + "", + ), + createTransaction( + "GetSignerPublicAccount", + "", + transactions.GetSignerPublicAccountTransaction(50).GetPrepareBlock(), + "", + ), + createTransaction( + "GetSignerAccountBalance", + "", + transactions.GetSignerAccountBalanceTransaction(30).GetPrepareBlock(), + "", + ), + createTransaction( + "GetSignerAccountAvailableBalance", + "", + transactions.GetSignerAccountAvailableBalanceTransaction(30).GetPrepareBlock(), + "", + ), + createTransaction( + "GetSignerAccountStorageUsed", + "", + transactions.GetSignerAccountStorageUsedTransaction(30).GetPrepareBlock(), + "", + ), + createTransaction( + "GetSignerAccountStorageCapacity", + "", + transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock(), + "", + ), + createTransaction( + "BorrowSignerAccountFlowTokenVault", + "import FungibleToken from 0x1\nimport FlowToken from 0x1", + transactions.BorrowSignerAccountFlowTokenVaultTransaction(30).GetPrepareBlock(), + "", + ), + createTransaction( + "BorrowSignerAccountFungibleTokenReceiver", + "import FungibleToken from 0x1\nimport FlowToken from 0x1", + transactions.BorrowSignerAccountFungibleTokenReceiverTransaction(30).GetPrepareBlock(), + "", + ), + createTransaction( + "TransferTokensToSelf", + "import FungibleToken from 0x1\nimport FlowToken from 0x1", + transactions.TransferTokensToSelfTransaction(30).GetPrepareBlock(), + "", + ), + createTransaction( + "CreateNewAccount", + "", + transactions.CreateNewAccountTransaction(10).GetPrepareBlock(), + "", + ), + createTransaction( + "CreateNewAccountWithContract", + "", + transactions.CreateNewAccountWithContractTransaction(10).GetPrepareBlock(), + "", + ), + createTransaction( + "DecodeHex", + "", + transactions.DecodeHexTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "RevertibleRandomNumber", + "", + transactions.RevertibleRandomTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "NumberToStringConversion", + "", + transactions.NumberToStringConversionTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ConcatenateString", + "", + transactions.ConcatenateStringTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "BorrowString", + "", + transactions.BorrowStringTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.BorrowStringTransaction.GetSetupTemplate(), + stringArrayOfLen(20, 100), + ), + ), + createTransaction( + "CopyString", + "", + transactions.CopyStringTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.CopyStringTransaction.GetSetupTemplate(), + stringArrayOfLen(20, 100), + ), + ), + createTransaction( + "CopyStringAndSaveDuplicate", + "", + transactions.CopyStringAndSaveADuplicateTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.CopyStringAndSaveADuplicateTransaction.GetSetupTemplate(), + stringArrayOfLen(20, 100), + ), + ), + createTransaction( + "StoreAndLoadDictString", + "", + transactions.StoreAndLoadDictStringTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "StoreLoadAndDestroyDictString", + "", + transactions.StoreLoadAndDestroyDictStringTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.StoreLoadAndDestroyDictStringTransaction.GetSetupTemplate(), + stringDictOfLen(100, 100), + ), + ), + createTransaction( + "BorrowDictString", + "", + transactions.BorrowDictStringTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.BorrowDictStringTransaction.GetSetupTemplate(), + stringDictOfLen(100, 100), + ), + ), + createTransaction( + "CopyDictString", + "", + transactions.CopyDictStringTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.CopyDictStringTransaction.GetSetupTemplate(), + stringDictOfLen(30, 100), + ), + ), + createTransaction( + "CopyDictStringAndSaveDuplicate", + "", + transactions.CopyDictStringAndSaveADuplicateTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.CopyDictStringAndSaveADuplicateTransaction.GetSetupTemplate(), + stringDictOfLen(20, 100), + ), + ), + createTransaction( + "LoadDictAndDestroy", + "", + transactions.LoadDictAndDestroyItTransaction.GetPrepareBlock(), + fmt.Sprintf( + transactions.LoadDictAndDestroyItTransaction.GetSetupTemplate(), + 100, + ), + ), + createTransaction( + "AddKeyToAccount", + "", + transactions.AddKeyToAccountTransaction(50).GetPrepareBlock(), + "", + ), + createTransaction( + "AddAndRevokeKeyToAccount", + "", + transactions.AddAndRevokeKeyToAccountTransaction(40).GetPrepareBlock(), + "", + ), + createTransaction( + "GetAccountKey", + "", + transactions.GetAccountKeyTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "GetContracts", + "", + transactions.GetContractsTransaction(100).GetPrepareBlock(), + transactions.GetContractsTransaction(100).GetSetupTemplate(), + ), + createTransaction( + "Hash", + "import Crypto from 0x1", + transactions.HashTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "StringToLower", + "", + transactions.StringToLowerTransaction(100, 100).GetPrepareBlock(), + "", + ), + createTransaction( + "GetCurrentBlock", + "", + transactions.GetCurrentBlockTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "GetBlockAt", + "", + transactions.GetBlockAtTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "DestroyResourceDictionary", + "", + transactions.DestroyResourceDictionaryTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ParseUFix64", + "", + transactions.ParseUFix64Transaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ParseFix64", + "", + transactions.ParseFix64Transaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ParseUInt64", + "", + transactions.ParseUInt64Transaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ParseInt64", + "", + transactions.ParseInt64Transaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ParseInt", + "", + transactions.ParseIntTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "IssueStorageCap", + "", + transactions.IssueStorageCapabilityTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "GetKeyCount", + "", + transactions.GetKeyCountTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "CreateKeyECDSAP256", + "", + createKeyECDSAP256Transaction.GetPrepareBlock(), + "", + ), + createTransaction( + "CreateKeyECDSAsecp256k1", + "", + createKeyECDSAsecp256k1Transaction.GetPrepareBlock(), + "", + ), + createTransaction( + "CreateKeyBLSBLS12381", + "", + createKeyBLSBLS12381Transaction.GetPrepareBlock(), + "", + ), + createTransaction( + "ArrayInsert", + "", + transactions.ArrayInsertTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ArrayInsertRemove", + "", + transactions.ArrayInsertRemoveTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ArrayInsertSetRemove", + "", + transactions.ArrayInsertSetRemoveTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ArrayInsertMap", + "", + transactions.ArrayInsertMapTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ArrayInsertFilterRemove", + "", + transactions.ArrayInsertFilterTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ArrayAppend", + "", + transactions.ArrayAppendTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "DictInsert", + "", + transactions.DictInsertTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "DictInsertRemove", + "", + transactions.DictInsertRemoveTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "DictInsertSetRemove", + "", + transactions.DictInsertSetRemoveTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "DictIterCopy", + "", + transactions.DictIterCopyTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "ArrayCreateBatch", + "", + transactions.ArrayCreateBatchTransaction(100).GetPrepareBlock(), + "", + ), + createTransaction( + "VerifySignatureTransaction", + "import Crypto from 0x1", + verifySignatureTransaction.GetPrepareBlock(), + "", + ), + createTransaction( + "AggregateBLSAggregateKeys", + "", + blsAggregateKeysTransaction.GetPrepareBlock(), + "", + ), + createTransaction( + "BLSVerifyProofOfPossession", + "", + blsVerifyProofOfPossessionTransaction.GetPrepareBlock(), + "", + ), } } func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { - runtime := NewTestRuntime() - contractsAddress := common.MustBytesToAddress([]byte{0x1}) senderAddress := common.MustBytesToAddress([]byte{0x2}) receiverAddress := common.MustBytesToAddress([]byte{0x3}) - accountCodes := map[common.Location][]byte{} - - var events []cadence.Event - - signerAccount := contractsAddress - - // Counter for generating unique account addresses - // Use uint64 to avoid overflow issues with large iteration counts - var accountCounter uint64 = 4 - - runtimeInterface := &TestRuntimeInterface{ - OnGetCode: func(location common.Location) (bytes []byte, err error) { - return accountCodes[location], nil - }, - Storage: NewTestLedger(nil, nil), - OnGetSigningAccounts: func() ([]common.Address, error) { - return []common.Address{signerAccount}, nil - }, - OnResolveLocation: NewSingleIdentifierLocationResolver(b), - OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { - return accountCodes[location], nil - }, - OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { - accountCodes[location] = code - return nil - }, - OnEmitEvent: func(event cadence.Event) error { - events = append(events, event) - return nil - }, - OnDecodeArgument: func(b []byte, t cadence.Type) (value cadence.Value, err error) { - return json.Decode(nil, b) - }, - OnGetAccountBalance: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnGetAccountAvailableBalance: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnGetStorageUsed: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnGetStorageCapacity: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnCreateAccount: func(payer Address) (address Address, err error) { - // Generate unique address from counter using binary encoding - accountCounter++ - addressBytes := make([]byte, 8) - binary.BigEndian.PutUint64(addressBytes, accountCounter) - result := interpreter.NewUnmeteredAddressValueFromBytes(addressBytes) - return result.ToAddress(), nil - }, - } + var signerAccount common.Address var environment Environment if useVM { @@ -193,53 +755,197 @@ func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { environment = NewBaseInterpreterEnvironment(Config{}) } - nextTransactionLocation := NewTransactionLocationGenerator() + // Helper function to create a fresh runtime interface with isolated storage + createRuntimeInterface := func() *TestRuntimeInterface { + accountCodes := map[common.Location][]byte{} + accountCounter := uint64(4) + created := false + signerAccount = contractsAddress - // Deploy Fungible Token contract + return &TestRuntimeInterface{ + OnGetCode: func(location common.Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]common.Address, error) { + return []common.Address{signerAccount}, nil + }, + OnResolveLocation: NewSingleIdentifierLocationResolver(b), + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnEmitEvent: func(event cadence.Event) error { + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (value cadence.Value, err error) { + return json.Decode(nil, b) + }, + OnGetAccountBalance: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetAccountAvailableBalance: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetStorageUsed: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetStorageCapacity: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnCreateAccount: func(payer Address) (address Address, err error) { + accountCounter++ + addressBytes := make([]byte, 8) + binary.BigEndian.PutUint64(addressBytes, accountCounter) + result := interpreter.NewUnmeteredAddressValueFromBytes(addressBytes) + return result.ToAddress(), nil + }, + OnValidatePublicKey: func(key *stdlib.PublicKey) error { + return nil + }, + OnVerifySignature: func( + signature []byte, + tag string, + signedData []byte, + publicKey []byte, + signatureAlgorithm SignatureAlgorithm, + hashAlgorithm HashAlgorithm, + ) (bool, error) { + return true, nil + }, + OnHash: func(data []byte, tag string, hashAlgorithm HashAlgorithm) ([]byte, error) { + return data, nil + }, + OnBLSVerifyPOP: func(pk *stdlib.PublicKey, s []byte) (bool, error) { + return true, nil + }, + OnBLSAggregateSignatures: func(sigs [][]byte) ([]byte, error) { + if len(sigs) == 0 { + return nil, fmt.Errorf("no signatures to aggregate") + } + return sigs[0], nil + }, + OnBLSAggregatePublicKeys: func(keys []*stdlib.PublicKey) (*stdlib.PublicKey, error) { + if len(keys) == 0 { + return nil, fmt.Errorf("no keys to aggregate") + } + return keys[0], nil + }, + OnAddAccountKey: func(address Address, publicKey *stdlib.PublicKey, hashAlgo HashAlgorithm, weight int) (*stdlib.AccountKey, error) { + return &stdlib.AccountKey{PublicKey: publicKey, HashAlgo: hashAlgo, Weight: weight}, nil + }, + OnGetAccountKey: func(address Address, index uint32) (*stdlib.AccountKey, error) { + return &stdlib.AccountKey{KeyIndex: index, PublicKey: &stdlib.PublicKey{}}, nil + }, + OnRemoveAccountKey: func(address Address, index uint32) (*stdlib.AccountKey, error) { + return &stdlib.AccountKey{KeyIndex: index, PublicKey: &stdlib.PublicKey{}}, nil + }, + OnAccountKeysCount: func(address Address) (uint32, error) { + return 1, nil + }, + OnGetAccountContractNames: func(address Address) ([]string, error) { + if created { + // ensures GetContractsTransaction only creates the contracts once + return []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"}, nil + } + created = true + return []string{}, nil + }, + } + } - err := runtime.ExecuteTransaction( - Script{ - Source: DeploymentTransaction( - "FungibleToken", - []byte(modifiedFungibleTokenContractInterface), - ), - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) - - // Deploy Flow Token contract - - err = runtime.ExecuteTransaction( - Script{ - Source: DeploymentTransaction("FlowToken", []byte(modifiedFlowContract)), - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) - - // Setup both user accounts for Flow Token - - for _, address := range []common.Address{ - senderAddress, - receiverAddress, - } { - - signerAccount = address + // Helper function to setup a fresh runtime with contracts deployed + setupRuntime := func() (TestRuntime, func() common.TransactionLocation, *TestRuntimeInterface) { + + runtimeInterface := createRuntimeInterface() + signerAccount = contractsAddress + + runtime := NewTestRuntime() + nextTransactionLocation := NewTransactionLocationGenerator() + + // Deploy Fungible Token contract + err := runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction( + "FungibleToken", + []byte(modifiedFungibleTokenContractInterface), + ), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Deploy Flow Token contract + err = runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction("FlowToken", []byte(modifiedFlowContract)), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Deploy Crypto contract + err = runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction("Crypto", []byte(realCryptoContract)), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Setup both user accounts for Flow Token + for _, address := range []common.Address{ + senderAddress, + receiverAddress, + } { + signerAccount = address + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(realSetupFlowTokenAccountTransaction), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + } + + // Mint 1000 FLOW to sender + mintAmount, err := cadence.NewUFix64("100000000000.0") + require.NoError(b, err) + + signerAccount = contractsAddress err = runtime.ExecuteTransaction( Script{ - Source: []byte(realSetupFlowTokenAccountTransaction), + Source: []byte(realMintFlowTokenTransaction), + Arguments: encodeArgs([]cadence.Value{ + cadence.Address(senderAddress), + mintAmount, + }), }, Context{ Interface: runtimeInterface, @@ -249,54 +955,37 @@ func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { }, ) require.NoError(b, err) + + // Set signer account to sender for benchmark transactions + signerAccount = senderAddress + + return runtime, nextTransactionLocation, runtimeInterface } - // Mint 1000 FLOW to sender - - mintAmount, err := cadence.NewUFix64("100000000000.0") - require.NoError(b, err) - - signerAccount = contractsAddress - - err = runtime.ExecuteTransaction( - Script{ - Source: []byte(realMintFlowTokenTransaction), - Arguments: encodeArgs([]cadence.Value{ - cadence.Address(senderAddress), - mintAmount, - }), - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) - - // Set signer account to sender for benchmark transactions - signerAccount = senderAddress - - // all benchmark transactions reuse the same location for _, transaction := range testTransactions { + b.Run(transaction.Name, func(b *testing.B) { + // Create fresh runtime and storage for this sub-benchmark + runtime, nextTransactionLocation, runtimeInterface := setupRuntime() + for b.Loop() { b.StopTimer() - err = runtime.ExecuteTransaction( - Script{ - Source: []byte(transaction.Setup), - Arguments: nil, - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) - + var err error + if transaction.Setup != "" { + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(transaction.Setup), + Arguments: nil, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + } b.StartTimer() err = runtime.ExecuteTransaction( @@ -327,3 +1016,7 @@ func BenchmarkRuntimeTransactionsInterpreter(b *testing.B) { func BenchmarkRuntimeTransactionsVM(b *testing.B) { benchmarkRuntimeTransactions(b, true) } + +func BenchmarkRuntimeTransactions(b *testing.B) { + benchmarkRuntimeTransactions(b, false) +} From 46055afbf602ba51e6ac905b93cb6d315bd60e8f Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Mon, 24 Nov 2025 17:45:52 -0500 Subject: [PATCH 07/14] Revert unused changes. --- bbq/vm/test/bench_transactions_test.go | 585 ------------------------- bbq/vm/test/utils.go | 9 - stdlib/account.go | 8 +- stdlib/builtin.go | 4 +- 4 files changed, 6 insertions(+), 600 deletions(-) delete mode 100644 bbq/vm/test/bench_transactions_test.go diff --git a/bbq/vm/test/bench_transactions_test.go b/bbq/vm/test/bench_transactions_test.go deleted file mode 100644 index 4b7f3ef3b..000000000 --- a/bbq/vm/test/bench_transactions_test.go +++ /dev/null @@ -1,585 +0,0 @@ -/* -* Cadence - The resource-oriented smart contract programming language -* -* Copyright Flow Foundation -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. - */ - -package test - -import ( - "fmt" - "strings" - "testing" - - "github.com/onflow/cadence-standard-transactions/transactions" - "github.com/onflow/cadence/activations" - "github.com/onflow/cadence/bbq" - "github.com/onflow/cadence/bbq/commons" - "github.com/onflow/cadence/bbq/compiler" - . "github.com/onflow/cadence/bbq/test_utils" - "github.com/onflow/cadence/bbq/vm" - "github.com/onflow/cadence/common" - "github.com/onflow/cadence/interpreter" - "github.com/onflow/cadence/sema" - "github.com/onflow/cadence/stdlib" - . "github.com/onflow/cadence/test_utils/interpreter_utils" - . "github.com/onflow/cadence/test_utils/runtime_utils" - . "github.com/onflow/cadence/test_utils/sema_utils" - "github.com/stretchr/testify/require" -) - -type testRandomGenerator struct{} - -func (*testRandomGenerator) ReadRandom([]byte) error { - return nil -} - -type Transaction struct { - Name string - Body string - Setup string -} - -var testTransactions []Transaction - -func createTransaction(name string, imports string, prepare string, setup string) Transaction { - return Transaction{ - Name: name, - Body: fmt.Sprintf( - ` - // %s - %s - - transaction(){ - prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { - %s - } - }`, - name, - imports, - prepare, - ), - Setup: fmt.Sprintf( - ` - transaction(){ - prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { - %s - } - }`, - setup, - ), - } -} - -func stringOfLen(length uint64) string { - someString := make([]byte, length) - for i := 0; i < len(someString); i++ { - someString[i] = 'x' - } - return string(someString) -} - -func stringArrayOfLen(arrayLen uint64, stringLen uint64) string { - builder := strings.Builder{} - builder.WriteRune('[') - for i := uint64(0); i < arrayLen; i++ { - if i > 0 { - builder.WriteRune(',') - } - builder.WriteRune('"') - builder.WriteString(stringOfLen(stringLen)) - builder.WriteRune('"') - } - builder.WriteRune(']') - return builder.String() -} - -func init() { - testTransactions = []Transaction{ - createTransaction( - "EmptyLoop", - "", - transactions.EmptyLoopTransaction(6000).GetPrepareBlock(), - "", - ), - createTransaction("AssertTrue", "", transactions.AssertTrueTransaction(3000).GetPrepareBlock(), ""), - createTransaction("GetSignerAddress", "", transactions.GetSignerAddressTransaction(4000).GetPrepareBlock(), ""), - createTransaction("GetSignerPublicAccount", "", transactions.GetSignerPublicAccountTransaction(3000).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountBalance", "", transactions.GetSignerAccountBalanceTransaction(30).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountAvailableBalance", "", transactions.GetSignerAccountAvailableBalanceTransaction(30).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountStorageUsed", "", transactions.GetSignerAccountStorageUsedTransaction(700).GetPrepareBlock(), ""), - createTransaction("GetSignerAccountStorageCapacity", "", transactions.GetSignerAccountStorageCapacityTransaction(30).GetPrepareBlock(), ""), - createTransaction("BorrowSignerAccountFlowTokenVault", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.BorrowSignerAccountFlowTokenVaultTransaction(700).GetPrepareBlock(), ""), - createTransaction("BorrowSignerAccountFungibleTokenReceiver", "import \"FungibleToken\"", transactions.BorrowSignerAccountFungibleTokenReceiverTransaction(400).GetPrepareBlock(), ""), - createTransaction("TransferTokensToSelf", "import \"FungibleToken\"\nimport \"FlowToken\"", transactions.TransferTokensToSelfTransaction(30).GetPrepareBlock(), ""), - createTransaction("CreateNewAccount", "", transactions.CreateNewAccountTransaction(10).GetPrepareBlock(), ""), - createTransaction("CreateNewAccountWithContract", "", transactions.CreateNewAccountWithContractTransaction(10).GetPrepareBlock(), ""), - createTransaction("DecodeHex", "", transactions.DecodeHexTransaction(900).GetPrepareBlock(), ""), - createTransaction("RevertibleRandomNumber", "", transactions.RevertibleRandomTransaction(2000).GetPrepareBlock(), ""), - createTransaction("NumberToStringConversion", "", transactions.NumberToStringConversionTransaction(3000).GetPrepareBlock(), ""), - createTransaction("ConcatenateString", "", transactions.ConcatenateStringTransaction(2000).GetPrepareBlock(), ""), - createTransaction("BorrowString", "", transactions.BorrowStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.BorrowStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), - createTransaction("CopyString", "", transactions.CopyStringTransaction.GetPrepareBlock(), fmt.Sprintf(transactions.CopyStringTransaction.GetSetupTemplate(), stringArrayOfLen(20, 2000))), - } -} - -func BenchmarkTransactionsVM(b *testing.B) { - // create addresses - contractsAddress := common.MustBytesToAddress([]byte{0x1}) - senderAddress := common.MustBytesToAddress([]byte{0x2}) - - locationHandler := newSingleAddressOrStringLocationHandler(b, contractsAddress) - - // make contracts available - compiledPrograms := CompiledPrograms{} - - burnerLocation := common.NewAddressLocation(nil, contractsAddress, "Burner") - viewResolverLocation := common.NewAddressLocation(nil, contractsAddress, "ViewResolver") - fungibleTokenLocation := common.NewAddressLocation(nil, contractsAddress, "FungibleToken") - metadataViewsLocation := common.NewAddressLocation(nil, contractsAddress, "MetadataViews") - fungibleTokenMetadataViewsLocation := common.NewAddressLocation(nil, contractsAddress, "FungibleTokenMetadataViews") - nonFungibleTokenLocation := common.NewAddressLocation(nil, contractsAddress, "NonFungibleToken") - flowTokenLocation := common.NewAddressLocation(nil, contractsAddress, "FlowToken") - - codes := map[common.Location][]byte{ - burnerLocation: []byte(realBurnerContract), - viewResolverLocation: []byte(realViewResolverContract), - fungibleTokenLocation: []byte(realFungibleTokenContract), - metadataViewsLocation: []byte(realMetadataViewsContract), - fungibleTokenMetadataViewsLocation: []byte(realFungibleTokenMetadataViewsContract), - nonFungibleTokenLocation: []byte(realNonFungibleTokenContract), - flowTokenLocation: []byte(realFlowContract), - } - - importHandler := func(location common.Location) *bbq.InstructionProgram { - imported, ok := compiledPrograms[location] - if !ok { - return nil - } - return imported.Program - } - - accountHandler := &testAccountHandler{ - emitEvent: func( - _ interpreter.ValueExportContext, - _ *sema.CompositeType, - _ []interpreter.Value, - ) { - // ignore - }, - getAccountBalance: func(address common.Address) (uint64, error) { - return 1000000000000000000, nil - }, - getAccountAvailableBalance: func(address common.Address) (uint64, error) { - return 1000000000000000000, nil - }, - getStorageUsed: func(address common.Address) (uint64, error) { - return 1000000000000000000, nil - }, - getStorageCapacity: func(address common.Address) (uint64, error) { - return 1000000000000000000, nil - }, - commitStorageTemporarily: func(context interpreter.ValueTransferContext) error { - return nil - }, - createAccount: func(payer common.Address) (common.Address, error) { - return common.Address{}, nil - }, - getAccountContractCode: func(location common.AddressLocation) ([]byte, error) { - return nil, nil - }, - updateAccountContractCode: func(location common.AddressLocation, code []byte) error { - return nil - }, - recordContractUpdate: func(location common.AddressLocation, value *interpreter.CompositeValue) { - // NO-OP - }, - contractUpdateRecorded: func(location common.AddressLocation) bool { - return false - }, - parseAndCheckProgram: func(code []byte, location common.Location, getAndSetProgram bool) (*interpreter.Program, error) { - res, err := ParseAndCheck(b, string(code)) - require.NoError(b, err) - return &interpreter.Program{ - Program: res.Program, - Elaboration: res.Elaboration, - }, nil - }, - loadContractValue: func(location common.AddressLocation, program *interpreter.Program, name string, invocation stdlib.DeployedContractConstructorInvocation) (*interpreter.CompositeValue, error) { - return nil, nil - }, - } - - vmRevertibleRandomFunction := stdlib.NewVMRevertibleRandomFunction(&testRandomGenerator{}) - accountConstructor := stdlib.NewVMAccountConstructor(accountHandler) - - // set up sema/compiler - semaConfig := &sema.Config{ - LocationHandler: locationHandler, - BaseValueActivationHandler: func(_ common.Location) *sema.VariableActivation { - // Only need to make the checker happy - activation := sema.NewVariableActivation(sema.BaseValueActivation) - activation.DeclareValue(stdlib.VMPanicFunction) - activation.DeclareValue(stdlib.VMAssertFunction) - activation.DeclareValue(stdlib.NewVMGetAccountFunction(nil)) - activation.DeclareValue(vmRevertibleRandomFunction) - activation.DeclareValue(accountConstructor) - return activation - }, - } - - compilerConfig := &compiler.Config{ - LocationHandler: locationHandler, - ImportHandler: importHandler, - ElaborationResolver: func(location common.Location) (*compiler.DesugaredElaboration, error) { - imported, ok := compiledPrograms[location] - if !ok { - return nil, fmt.Errorf("cannot find elaboration for %s", location) - } - return imported.DesugaredElaboration, nil - }, - BuiltinGlobalsProvider: func(_ common.Location) *activations.Activation[compiler.GlobalImport] { - activation := activations.NewActivation(nil, compiler.DefaultBuiltinGlobals()) - - activation.Set( - stdlib.AssertFunctionName, - compiler.NewGlobalImport(stdlib.AssertFunctionName), - ) - - activation.Set( - stdlib.GetAccountFunctionName, - compiler.NewGlobalImport(stdlib.GetAccountFunctionName), - ) - - activation.Set( - stdlib.PanicFunctionName, - compiler.NewGlobalImport(stdlib.PanicFunctionName), - ) - - activation.Set( - vmRevertibleRandomFunction.Name, - compiler.NewGlobalImport(vmRevertibleRandomFunction.Name), - ) - - activation.Set( - accountConstructor.Name, - compiler.NewGlobalImport(accountConstructor.Name), - ) - - return activation - }, - } - - // Parse and check contracts - - for _, location := range []common.Location{ - burnerLocation, - viewResolverLocation, - fungibleTokenLocation, - nonFungibleTokenLocation, - metadataViewsLocation, - fungibleTokenMetadataViewsLocation, - flowTokenLocation, - } { - _ = ParseCheckAndCompileCodeWithOptions( - b, - string(codes[location]), - location, - ParseCheckAndCompileOptions{ - ParseAndCheckOptions: &ParseAndCheckOptions{ - Location: location, - CheckerConfig: semaConfig, - }, - CompilerConfig: compilerConfig, - }, - compiledPrograms, - ) - } - - // set up VM - vmConfig := vm.NewConfig(NewUnmeteredInMemoryStorage()) - - vmConfig.CapabilityBorrowHandler = func( - context interpreter.BorrowCapabilityControllerContext, - address interpreter.AddressValue, - capabilityID interpreter.UInt64Value, - wantedBorrowType *sema.ReferenceType, - capabilityBorrowType *sema.ReferenceType, - ) interpreter.ReferenceValue { - return stdlib.BorrowCapabilityController( - context, - address, - capabilityID, - wantedBorrowType, - capabilityBorrowType, - accountHandler, - ) - } - - vmConfig.OnEventEmitted = func( - _ interpreter.ValueExportContext, - _ *sema.CompositeType, - _ []interpreter.Value, - ) error { - // NO-OP - return nil - } - - vmConfig.AccountHandlerFunc = func( - context interpreter.AccountCreationContext, - address interpreter.AddressValue, - ) interpreter.Value { - return stdlib.NewAccountValue(context, accountHandler, address) - } - - contractValues := make(map[common.Location]*interpreter.CompositeValue) - vmConfig.ContractValueHandler = func( - _ *vm.Context, - location common.Location, - ) *interpreter.CompositeValue { - return contractValues[location] - } - - vmConfig.ImportHandler = importHandler - - vmConfig.InjectedCompositeFieldsHandler = func( - context interpreter.AccountCreationContext, - _ common.Location, - _ string, - _ common.CompositeKind, - ) map[string]interpreter.Value { - - accountRef := stdlib.NewAccountReferenceValue( - context, - accountHandler, - interpreter.NewAddressValue(nil, contractsAddress), - interpreter.FullyEntitledAccountAccess, - ) - - return map[string]interpreter.Value{ - sema.ContractAccountFieldName: accountRef, - } - } - - vmConfig.BuiltinGlobalsProvider = func(_ common.Location) *activations.Activation[vm.Variable] { - activation := activations.NewActivation(nil, vm.DefaultBuiltinGlobals()) - - panicVariable := &interpreter.SimpleVariable{} - panicVariable.InitializeWithValue(stdlib.VMPanicFunction.Value) - activation.Set( - stdlib.PanicFunctionName, - panicVariable, - ) - - assertVariable := &interpreter.SimpleVariable{} - assertVariable.InitializeWithValue(stdlib.VMAssertFunction.Value) - activation.Set( - stdlib.AssertFunctionName, - assertVariable, - ) - - getAccountVariable := &interpreter.SimpleVariable{} - getAccountVariable.InitializeWithValue(stdlib.NewVMGetAccountFunction(accountHandler).Value) - activation.Set( - stdlib.GetAccountFunctionName, - getAccountVariable, - ) - - for _, vmFunction := range []stdlib.VMFunction{ - stdlib.NewVMAccountCapabilitiesPublishFunction(accountHandler), - stdlib.NewVMAccountStorageCapabilitiesIssueFunction(accountHandler), - stdlib.NewVMAccountCapabilitiesGetFunction(accountHandler, true), - stdlib.NewVMAccountContractsChangeFunction(accountHandler, false), - } { - variable := &interpreter.SimpleVariable{} - variable.InitializeWithValue(vmFunction.FunctionValue) - activation.Set( - commons.TypeQualifiedName( - vmFunction.BaseType, - vmFunction.FunctionValue.Name, - ), - variable, - ) - } - - for _, nativeFunction := range []stdlib.StandardLibraryValue{ - vmRevertibleRandomFunction, - accountConstructor, - } { - variable := &interpreter.SimpleVariable{} - variable.InitializeWithValue(nativeFunction.Value) - activation.Set( - nativeFunction.Name, - variable, - ) - } - - return activation - } - - vmConfig = PrepareVMConfig(b, vmConfig, compiledPrograms) - - // Initialize contracts - for _, location := range []common.Location{ - metadataViewsLocation, - fungibleTokenMetadataViewsLocation, - flowTokenLocation, - } { - compiledProgram := compiledPrograms[location] - _, contractValue := initializeContract( - b, - location, - compiledProgram.Program, - vmConfig, - ) - - contractValues[location] = contractValue - } - - nextTransactionLocation := NewTransactionLocationGenerator() - txLocation := nextTransactionLocation() - - // setup account, mint tokens - setupAccountProgram := ParseCheckAndCompileCodeWithOptions( - b, - realFlowTokenSetupAccountTransaction, - txLocation, - ParseCheckAndCompileOptions{ - ParseAndCheckOptions: &ParseAndCheckOptions{ - Location: txLocation, - CheckerConfig: semaConfig, - }, - CompilerConfig: compilerConfig, - }, - compiledPrograms, - ) - - setupAccountVM := vm.NewVM(txLocation, setupAccountProgram, vmConfig) - - setupAccountAuthorizer := stdlib.NewAccountReferenceValue( - setupAccountVM.Context(), - accountHandler, - interpreter.NewAddressValue(nil, senderAddress), - interpreter.FullyEntitledAccountAccess, - ) - - err := setupAccountVM.InvokeTransaction(nil, setupAccountAuthorizer) - require.NoError(b, err) - - txLocation = nextTransactionLocation() - - mintTokensTxProgram := ParseCheckAndCompileCodeWithOptions( - b, - realFlowTokenMintTokensTransaction, - txLocation, - ParseCheckAndCompileOptions{ - ParseAndCheckOptions: &ParseAndCheckOptions{ - Location: txLocation, - CheckerConfig: semaConfig, - }, - CompilerConfig: compilerConfig, - }, - compiledPrograms, - ) - - mintTxVM := vm.NewVM(txLocation, mintTokensTxProgram, vmConfig) - - total := uint64(1000000) * sema.Fix64Factor - - mintTxArgs := []vm.Value{ - interpreter.AddressValue(senderAddress), - interpreter.NewUnmeteredUFix64Value(total), - } - - // Use the same authorizations as the one defined in the transaction. - semaAuthorization := sema.NewEntitlementSetAccess( - []*sema.EntitlementType{ - sema.BorrowValueType, - }, - sema.Conjunction, - ) - authorization := interpreter.ConvertSemaAccessToStaticAuthorization(nil, semaAuthorization) - - mintTxAuthorizer := stdlib.NewAccountReferenceValue( - mintTxVM.Context(), - accountHandler, - interpreter.AddressValue(contractsAddress), - authorization, - ) - - err = mintTxVM.InvokeTransaction(mintTxArgs, mintTxAuthorizer) - require.NoError(b, err) - require.Equal(b, 0, mintTxVM.StackSize()) - - // all benchmark transactions use the same location, this prevents compiledPrograms from blowing up - txLocation = nextTransactionLocation() - - authorizer := stdlib.NewAccountReferenceValue( - mintTxVM.Context(), // ctx shouldn't matter - accountHandler, - interpreter.NewAddressValue(nil, senderAddress), - interpreter.FullyEntitledAccountAccess, - ) - - for _, transaction := range testTransactions { - b.Run(transaction.Name, func(b *testing.B) { - for b.Loop() { - b.StopTimer() - - setupProgram := ParseCheckAndCompileCodeWithOptions( - b, - transaction.Setup, - txLocation, - ParseCheckAndCompileOptions{ - ParseAndCheckOptions: &ParseAndCheckOptions{ - Location: txLocation, - CheckerConfig: semaConfig, - }, - CompilerConfig: compilerConfig, - }, - compiledPrograms, - ) - setupVM := vm.NewVM(txLocation, setupProgram, vmConfig) - - err := setupVM.InvokeTransaction(nil, authorizer) - require.NoError(b, err) - require.Equal(b, 0, setupVM.StackSize()) - - program := ParseCheckAndCompileCodeWithOptions( - b, - transaction.Body, - txLocation, - ParseCheckAndCompileOptions{ - ParseAndCheckOptions: &ParseAndCheckOptions{ - Location: txLocation, - CheckerConfig: semaConfig, - }, - CompilerConfig: compilerConfig, - }, - compiledPrograms, - ) - - vmInstance := vm.NewVM(txLocation, program, vmConfig) - b.StartTimer() - - err = vmInstance.InvokeTransaction(nil, authorizer) - - b.StopTimer() - require.NoError(b, err) - b.StartTimer() - } - }) - } -} diff --git a/bbq/vm/test/utils.go b/bbq/vm/test/utils.go index 8975571a5..098e48e7a 100644 --- a/bbq/vm/test/utils.go +++ b/bbq/vm/test/utils.go @@ -106,18 +106,9 @@ type testAccountHandler struct { removeAccountContractCode func(location common.AddressLocation) error recordContractRemoval func(location common.AddressLocation) getAccountContractNames func(address common.Address) ([]string, error) - createAccount func(payer common.Address) (common.Address, error) } var _ stdlib.AccountHandler = &testAccountHandler{} -var _ stdlib.AccountCreator = &testAccountHandler{} - -func (t *testAccountHandler) CreateAccount(payer common.Address) (common.Address, error) { - if t.createAccount == nil { - panic(errors.NewUnexpectedError("unexpected call to CreateAccount")) - } - return t.createAccount(payer) -} func (t *testAccountHandler) GenerateAccountID(address common.Address) (uint64, error) { if t.generateAccountID == nil { diff --git a/stdlib/account.go b/stdlib/account.go index d7659ab3e..34269034b 100644 --- a/stdlib/account.go +++ b/stdlib/account.go @@ -362,13 +362,13 @@ func newAccountContractsValue( return interpreter.NewAccountContractsValue( context, addressValue, - NewInterpreterAccountContractsChangeFunction( + newInterpreterAccountContractsChangeFunction( context, handler, addressValue, false, ), - NewInterpreterAccountContractsChangeFunction( + newInterpreterAccountContractsChangeFunction( context, handler, addressValue, @@ -1742,7 +1742,7 @@ func nativeAccountContractsChangeFunction( // newInterpreterAccountContractsChangeFunction called when e.g. // - adding: `Account.contracts.add(name: "Foo", code: [...])` (isUpdate = false) // - updating: `Account.contracts.update(name: "Foo", code: [...])` (isUpdate = true) -func NewInterpreterAccountContractsChangeFunction( +func newInterpreterAccountContractsChangeFunction( context interpreter.FunctionCreationContext, handler AccountContractAdditionAndNamesHandler, addressValue interpreter.AddressValue, @@ -1764,7 +1764,7 @@ func NewInterpreterAccountContractsChangeFunction( } } -func NewVMAccountContractsChangeFunction( +func newVMAccountContractsChangeFunction( handler AccountContractAdditionAndNamesHandler, isUpdate bool, ) VMFunction { diff --git a/stdlib/builtin.go b/stdlib/builtin.go index 3c29acb83..76d39f9ef 100644 --- a/stdlib/builtin.go +++ b/stdlib/builtin.go @@ -115,8 +115,8 @@ func VMFunctions(handler StandardLibraryHandler) []VMFunction { NewVMAccountContractsGetFunction(handler), NewVMAccountContractsBorrowFunction(handler), - NewVMAccountContractsChangeFunction(handler, true), - NewVMAccountContractsChangeFunction(handler, false), + newVMAccountContractsChangeFunction(handler, true), + newVMAccountContractsChangeFunction(handler, false), newVMAccountContractsTryUpdateFunction(handler), newVMAccountContractsRemoveFunction(handler), From 102e47e69ece272a2a6e38916e9fea13e05e2312 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Tue, 25 Nov 2025 13:12:06 -0500 Subject: [PATCH 08/14] Update go mod dependency, remove local replace. --- go.mod | 10 +++++----- go.sum | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 868966306..4a9ef6c29 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/onflow/cadence -go 1.25.0 +go 1.24.0 + +toolchain go1.24.3 require ( github.com/SaveTheRbtz/mph v0.1.1-0.20240117162131-4166ec7869bc @@ -17,10 +19,10 @@ require ( github.com/leanovate/gopter v0.2.11 github.com/logrusorgru/aurora/v4 v4.0.0 github.com/onflow/atree v0.12.0 - github.com/onflow/cadence-standard-transactions v0.0.0-00010101000000-000000000000 + github.com/onflow/cadence-standard-transactions v0.1.0 github.com/onflow/crypto v0.25.3 github.com/onflow/fixed-point v0.1.1 - github.com/onflow/flow-go-sdk v1.9.3 + github.com/onflow/flow-go-sdk v1.9.1 github.com/rivo/uniseg v0.4.7 github.com/schollz/progressbar/v3 v3.18.0 github.com/stretchr/testify v1.11.1 @@ -69,5 +71,3 @@ require ( gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -replace github.com/onflow/cadence-standard-transactions => /Users/rayz/Desktop/Work/cadence-standard-transactions diff --git a/go.sum b/go.sum index f6a0ac071..6526aedcd 100644 --- a/go.sum +++ b/go.sum @@ -263,12 +263,14 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/onflow/atree v0.12.0 h1:X7/UEPyCaaEQ1gCg11KDvfyEtEeQLhtRtxMHjAiH/Co= github.com/onflow/atree v0.12.0/go.mod h1:qdZcfLQwPirHcNpLiK+2t3KAo+SAb9Si6TqurE6pykE= +github.com/onflow/cadence-standard-transactions v0.1.0 h1:CuHlQgPIUeWQaaSU5w3euAvO1xUz7nzp3S5Ui8bOhPs= +github.com/onflow/cadence-standard-transactions v0.1.0/go.mod h1:C5z6Ka+Ta7zZC7uYDUhPwwS/HwrT0q3Yp6BiDba53bw= github.com/onflow/crypto v0.25.3 h1:XQ3HtLsw8h1+pBN+NQ1JYM9mS2mVXTyg55OldaAIF7U= github.com/onflow/crypto v0.25.3/go.mod h1:+1igaXiK6Tjm9wQOBD1EGwW7bYWMUGKtwKJ/2QL/OWs= github.com/onflow/fixed-point v0.1.1 h1:j0jYZVO8VGyk1476alGudEg7XqCkeTVxb5ElRJRKS90= github.com/onflow/fixed-point v0.1.1/go.mod h1:gJdoHqKtToKdOZbvryJvDZfcpzC7d2fyWuo3ZmLtcGY= -github.com/onflow/flow-go-sdk v1.9.3 h1:VaJaZUJdcjdBBdRV0GmzzCBzgt9EUCJfqnVffdwaY0w= -github.com/onflow/flow-go-sdk v1.9.3/go.mod h1:HJRNJAMN+EkrdvJHB4cek2SwMFF5g66bKu071kZ1rIE= +github.com/onflow/flow-go-sdk v1.9.1 h1:e3dTnZj9UVTPwnBj9OsSr1MexdWsUs/C8Wg5VpQ1XN4= +github.com/onflow/flow-go-sdk v1.9.1/go.mod h1:CnYk7bGwcsSSF1QwALuu1MaHNMcLyofpif7SJT+Qvpg= github.com/onflow/flow/protobuf/go/flow v0.4.18 h1:KOujA6lg9kTXCV6oK0eErD1rwRnM9taKZss3Szi+T3Q= github.com/onflow/flow/protobuf/go/flow v0.4.18/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= From 7df0cfac9d42906be7b14fca3ce6a90ddec1538e Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Tue, 25 Nov 2025 13:43:09 -0500 Subject: [PATCH 09/14] Fix import formatting. --- runtime/bench_standard_transactions_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go index 16cc885f9..09831f156 100644 --- a/runtime/bench_standard_transactions_test.go +++ b/runtime/bench_standard_transactions_test.go @@ -27,18 +27,19 @@ import ( "strings" "testing" + flowsdk "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go-sdk/crypto" "github.com/stretchr/testify/require" - "github.com/onflow/cadence" "github.com/onflow/cadence-standard-transactions/transactions" + + "github.com/onflow/cadence" "github.com/onflow/cadence/common" "github.com/onflow/cadence/encoding/json" "github.com/onflow/cadence/interpreter" . "github.com/onflow/cadence/runtime" "github.com/onflow/cadence/stdlib" . "github.com/onflow/cadence/test_utils/runtime_utils" - flowsdk "github.com/onflow/flow-go-sdk" - "github.com/onflow/flow-go-sdk/crypto" ) var realCryptoContract = ` From 6c0171500ad027c6d83ef8f3fc432a8857a4379a Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Tue, 25 Nov 2025 15:38:10 -0500 Subject: [PATCH 10/14] Clean up. --- runtime/bench_standard_transactions_test.go | 70 ++++---------------- tools/compatibility-check/go.mod | 25 ++++--- tools/compatibility-check/go.sum | 73 ++++++++++----------- 3 files changed, 60 insertions(+), 108 deletions(-) diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go index 09831f156..4df6d2a98 100644 --- a/runtime/bench_standard_transactions_test.go +++ b/runtime/bench_standard_transactions_test.go @@ -23,8 +23,6 @@ import ( "encoding/binary" "encoding/hex" "fmt" - "strconv" - "strings" "testing" flowsdk "github.com/onflow/flow-go-sdk" @@ -251,53 +249,6 @@ func createTransaction(name string, imports string, prepare string, setup string } } -func stringOfLen(length uint64) string { - someString := make([]byte, length) - for i := 0; i < len(someString); i++ { - someString[i] = 'x' - } - return string(someString) -} - -func stringArrayOfLen(arrayLen uint64, stringLen uint64) string { - builder := strings.Builder{} - builder.WriteRune('[') - for i := uint64(0); i < arrayLen; i++ { - if i > 0 { - builder.WriteRune(',') - } - builder.WriteRune('"') - builder.WriteString(stringOfLen(stringLen)) - builder.WriteRune('"') - } - builder.WriteRune(']') - return builder.String() -} - -func stringDictOfLen(dictLen uint64, stringLen uint64) string { - builder := strings.Builder{} - builder.WriteRune('{') - for i := uint64(0); i < dictLen; i++ { - if i > 0 { - builder.WriteRune(',') - } - builder.WriteRune('"') - someString := make([]byte, stringLen) - for i := 0; i < len(someString); i++ { - someString[i] = 'x' - } - builder.WriteString(string(someString)) - builder.WriteString(strconv.Itoa(int(i))) - builder.WriteRune('"') - builder.WriteRune(':') - builder.WriteRune('"') - builder.WriteString(string(someString)) - builder.WriteRune('"') - } - builder.WriteRune('}') - return builder.String() -} - func init() { // create key transactions createKeyECDSAP256Transaction, err := transactions.CreateKeyECDSAP256Transaction(100) @@ -469,7 +420,7 @@ func init() { transactions.BorrowStringTransaction.GetPrepareBlock(), fmt.Sprintf( transactions.BorrowStringTransaction.GetSetupTemplate(), - stringArrayOfLen(20, 100), + transactions.StringArrayOfLen(20, 100), ), ), createTransaction( @@ -478,7 +429,7 @@ func init() { transactions.CopyStringTransaction.GetPrepareBlock(), fmt.Sprintf( transactions.CopyStringTransaction.GetSetupTemplate(), - stringArrayOfLen(20, 100), + transactions.StringArrayOfLen(20, 100), ), ), createTransaction( @@ -487,7 +438,7 @@ func init() { transactions.CopyStringAndSaveADuplicateTransaction.GetPrepareBlock(), fmt.Sprintf( transactions.CopyStringAndSaveADuplicateTransaction.GetSetupTemplate(), - stringArrayOfLen(20, 100), + transactions.StringArrayOfLen(20, 100), ), ), createTransaction( @@ -502,7 +453,7 @@ func init() { transactions.StoreLoadAndDestroyDictStringTransaction.GetPrepareBlock(), fmt.Sprintf( transactions.StoreLoadAndDestroyDictStringTransaction.GetSetupTemplate(), - stringDictOfLen(100, 100), + transactions.StringDictOfLen(100, 100), ), ), createTransaction( @@ -511,7 +462,7 @@ func init() { transactions.BorrowDictStringTransaction.GetPrepareBlock(), fmt.Sprintf( transactions.BorrowDictStringTransaction.GetSetupTemplate(), - stringDictOfLen(100, 100), + transactions.StringDictOfLen(100, 100), ), ), createTransaction( @@ -520,7 +471,7 @@ func init() { transactions.CopyDictStringTransaction.GetPrepareBlock(), fmt.Sprintf( transactions.CopyDictStringTransaction.GetSetupTemplate(), - stringDictOfLen(30, 100), + transactions.StringDictOfLen(30, 100), ), ), createTransaction( @@ -529,7 +480,7 @@ func init() { transactions.CopyDictStringAndSaveADuplicateTransaction.GetPrepareBlock(), fmt.Sprintf( transactions.CopyDictStringAndSaveADuplicateTransaction.GetSetupTemplate(), - stringDictOfLen(20, 100), + transactions.StringDictOfLen(20, 100), ), ), createTransaction( @@ -971,6 +922,7 @@ func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { for b.Loop() { b.StopTimer() + // set up everything for the transaction var err error if transaction.Setup != "" { err = runtime.ExecuteTransaction( @@ -987,16 +939,18 @@ func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { ) require.NoError(b, err) } + source := []byte(transaction.Body) + location := nextTransactionLocation() b.StartTimer() err = runtime.ExecuteTransaction( Script{ - Source: []byte(transaction.Body), + Source: source, Arguments: nil, }, Context{ Interface: runtimeInterface, - Location: nextTransactionLocation(), + Location: location, Environment: environment, UseVM: useVM, }, diff --git a/tools/compatibility-check/go.mod b/tools/compatibility-check/go.mod index e4a3fcc5f..c7b7c2fc9 100644 --- a/tools/compatibility-check/go.mod +++ b/tools/compatibility-check/go.mod @@ -5,7 +5,7 @@ go 1.24.0 toolchain go1.24.3 require ( - github.com/onflow/cadence v1.1.1-0.20241018202510-7f1b6fbc57c2 + github.com/onflow/cadence v1.8.2 github.com/onflow/flow-core-contracts/lib/go/contracts v1.4.0 github.com/onflow/flow-go v0.38.0-preview.0.0.20241018215103-774056466e36 github.com/rs/zerolog v1.29.0 @@ -17,20 +17,20 @@ require ( github.com/bits-and-blooms/bitset v1.24.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/coreos/go-semver v0.3.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/ethereum/go-ethereum v1.13.10 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fxamacker/cbor/v2 v2.9.1-0.20251019205732-39888e6be013 // indirect github.com/fxamacker/circlehash v0.3.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/uint256 v1.3.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/k0kubun/pp/v3 v3.5.0 // indirect github.com/kevinburke/go-bindata v3.24.0+incompatible // indirect - github.com/klauspost/cpuid/v2 v2.2.6 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/logrusorgru/aurora/v4 v4.0.0 // indirect @@ -51,17 +51,16 @@ require ( github.com/onflow/flow-core-contracts/lib/go/templates v1.3.3-0.20241017220455-79fdc6c8ba53 // indirect github.com/onflow/flow-ft/lib/go/contracts v1.0.1 // indirect github.com/onflow/flow-ft/lib/go/templates v1.0.1 // indirect - github.com/onflow/flow-go-sdk v1.1.0 // indirect + github.com/onflow/flow-go-sdk v1.9.1 // indirect github.com/onflow/flow-nft/lib/go/contracts v1.2.2 // indirect github.com/onflow/flow-nft/lib/go/templates v1.2.1 // indirect - github.com/onflow/flow/protobuf/go/flow v0.4.7 // indirect - github.com/onflow/go-ethereum v1.14.7 // indirect + github.com/onflow/flow/protobuf/go/flow v0.4.18 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/psiemens/sconfig v0.1.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.0 // indirect @@ -79,13 +78,13 @@ require ( github.com/zeebo/blake3 v0.2.4 // indirect go.opentelemetry.io/otel v1.37.0 // indirect golang.org/x/crypto v0.41.0 // indirect - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect + golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/text v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.16.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.4.1 // indirect diff --git a/tools/compatibility-check/go.sum b/tools/compatibility-check/go.sum index a3ac4e754..2478775cf 100644 --- a/tools/compatibility-check/go.sum +++ b/tools/compatibility-check/go.sum @@ -74,8 +74,8 @@ github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/e github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw= -github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= +github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= @@ -93,10 +93,11 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= @@ -115,8 +116,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.13.10 h1:Ppdil79nN+Vc+mXfge0AuUgmKWuVv4eMqzoIVSdqZek= -github.com/ethereum/go-ethereum v1.13.10/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/ethereum/go-ethereum v1.16.7 h1:qeM4TvbrWK0UC0tgkZ7NiRsmBGwsjqc64BHo20U59UQ= +github.com/ethereum/go-ethereum v1.16.7/go.mod h1:Fs6QebQbavneQTYcA39PEKv2+zIjX7rPUZ14DER46wk= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -177,8 +178,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -234,8 +235,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/uint256 v1.3.0 h1:4wdcm/tnd0xXdu7iS3ruNvxkWwrb4aeBQv19ayYn8F4= -github.com/holiman/uint256 v1.3.0/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/huandu/go-clone v1.6.0 h1:HMo5uvg4wgfiy5FoGOqlFLQED/VGRm2D9Pi8g1FXPGc= github.com/huandu/go-clone v1.6.0/go.mod h1:ReGivhG6op3GYr+UY3lS6mxjKp7MIGTknuU5TbTVaXE= github.com/huandu/go-clone/generic v1.7.2 h1:47pQphxs1Xc9cVADjOHN+Bm5D0hNagwH9UXErbxgVKA= @@ -278,8 +279,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= +github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -312,7 +313,7 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= @@ -357,16 +358,14 @@ github.com/onflow/flow-ft/lib/go/templates v1.0.1 h1:FDYKAiGowABtoMNusLuRCILIZDt github.com/onflow/flow-ft/lib/go/templates v1.0.1/go.mod h1:uQ8XFqmMK2jxyBSVrmyuwdWjTEb+6zGjRYotfDJ5pAE= github.com/onflow/flow-go v0.38.0-preview.0.0.20241018215103-774056466e36 h1:Bt7WUgRd3C3o93A9KL+cuLwxzrMgfpqKGxTTZF97RJY= github.com/onflow/flow-go v0.38.0-preview.0.0.20241018215103-774056466e36/go.mod h1:ZWA2u8gALTYLl5L9M+2ylotWu90kfDmm5RnLNezew/c= -github.com/onflow/flow-go-sdk v1.1.0 h1:DT8P3B3oAicOOXugdev4s1IEKHsiLS9T7MovFcTzB2s= -github.com/onflow/flow-go-sdk v1.1.0/go.mod h1:21g1pqP9Wy8RBXdenNsjzADwbtWNOViUCnfNZwr3trM= +github.com/onflow/flow-go-sdk v1.9.1 h1:e3dTnZj9UVTPwnBj9OsSr1MexdWsUs/C8Wg5VpQ1XN4= +github.com/onflow/flow-go-sdk v1.9.1/go.mod h1:CnYk7bGwcsSSF1QwALuu1MaHNMcLyofpif7SJT+Qvpg= github.com/onflow/flow-nft/lib/go/contracts v1.2.2 h1:XFERNVUDGbZ4ViZjt7P1cGD80mO1PzUJYPfdhXFsGbQ= github.com/onflow/flow-nft/lib/go/contracts v1.2.2/go.mod h1:eZ9VMMNfCq0ho6kV25xJn1kXeCfxnkhj3MwF3ed08gY= github.com/onflow/flow-nft/lib/go/templates v1.2.1 h1:SAALMZPDw9Eb9p5kSLnmnFxjyig1MLiT4JUlLp0/bSE= github.com/onflow/flow-nft/lib/go/templates v1.2.1/go.mod h1:W6hOWU0xltPqNpv9gQX8Pj8Jtf0OmRxc1XX2V0kzJaI= -github.com/onflow/flow/protobuf/go/flow v0.4.7 h1:iP6DFx4wZ3ETORsyeqzHu7neFT3d1CXF6wdK+AOOjmc= -github.com/onflow/flow/protobuf/go/flow v0.4.7/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= -github.com/onflow/go-ethereum v1.14.7 h1:gg3awYqI02e3AypRdpJKEvNTJ6kz/OhAqRti0h54Wlc= -github.com/onflow/go-ethereum v1.14.7/go.mod h1:zV14QLrXyYu5ucvcwHUA0r6UaqveqbXaehAVQJlSW+I= +github.com/onflow/flow/protobuf/go/flow v0.4.18 h1:KOujA6lg9kTXCV6oK0eErD1rwRnM9taKZss3Szi+T3Q= +github.com/onflow/flow/protobuf/go/flow v0.4.18/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -379,8 +378,9 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= @@ -406,8 +406,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -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/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/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= @@ -542,8 +542,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -606,8 +606,8 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -674,7 +674,6 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= @@ -817,11 +816,11 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4= +google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a h1:tPE/Kp+x9dMSwUm/uM0JKK0IfdiJkwAbSMSeZBXXJXc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -839,8 +838,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -853,8 +852,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 8efd49dcf960cbfeecda90770c3b2ea599a88d58 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Tue, 25 Nov 2025 15:44:43 -0500 Subject: [PATCH 11/14] Remove helper benchmark function. --- runtime/bench_standard_transactions_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go index 4df6d2a98..cb3a1e86a 100644 --- a/runtime/bench_standard_transactions_test.go +++ b/runtime/bench_standard_transactions_test.go @@ -971,7 +971,3 @@ func BenchmarkRuntimeTransactionsInterpreter(b *testing.B) { func BenchmarkRuntimeTransactionsVM(b *testing.B) { benchmarkRuntimeTransactions(b, true) } - -func BenchmarkRuntimeTransactions(b *testing.B) { - benchmarkRuntimeTransactions(b, false) -} From 7db2092898f945c05b84d171c37900947a92a23f Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Wed, 26 Nov 2025 14:31:16 -0500 Subject: [PATCH 12/14] Skip empty setup transactions. --- runtime/bench_standard_transactions_test.go | 24 ++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go index cb3a1e86a..b829e70f1 100644 --- a/runtime/bench_standard_transactions_test.go +++ b/runtime/bench_standard_transactions_test.go @@ -221,6 +221,18 @@ type Transaction struct { var testTransactions []Transaction func createTransaction(name string, imports string, prepare string, setup string) Transaction { + setupBody := "" + if setup != "" { + setupBody = fmt.Sprintf( + ` + transaction(){ + prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { + %s + } + }`, + setup, + ) + } return Transaction{ Name: name, Body: fmt.Sprintf( @@ -237,15 +249,7 @@ func createTransaction(name string, imports string, prepare string, setup string imports, prepare, ), - Setup: fmt.Sprintf( - ` - transaction(){ - prepare(signer: auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account) { - %s - } - }`, - setup, - ), + Setup: setupBody, } } @@ -577,7 +581,7 @@ func init() { "", ), createTransaction( - "IssueStorageCap", + "IssueStorageCapability", "", transactions.IssueStorageCapabilityTransaction(100).GetPrepareBlock(), "", From 9d480b1974a7f80a01057010916ea20e1a60baf1 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Wed, 3 Dec 2025 11:49:43 -0500 Subject: [PATCH 13/14] Update runtime/bench_standard_transactions_test.go Co-authored-by: Supun Setunga --- runtime/bench_standard_transactions_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go index b829e70f1..00bb98fbe 100644 --- a/runtime/bench_standard_transactions_test.go +++ b/runtime/bench_standard_transactions_test.go @@ -815,7 +815,7 @@ func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { } // Helper function to setup a fresh runtime with contracts deployed - setupRuntime := func() (TestRuntime, func() common.TransactionLocation, *TestRuntimeInterface) { + setupRuntime := func(b *testing.B) (TestRuntime, func() common.TransactionLocation, *TestRuntimeInterface) { runtimeInterface := createRuntimeInterface() signerAccount = contractsAddress From 5747fa78bc8999b0192a215a8bcb48dc08ce4de6 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Thu, 4 Dec 2025 12:57:53 -0500 Subject: [PATCH 14/14] Simplify crypto transactions, refactor. --- go.mod | 9 +- go.sum | 18 +- runtime/bench_standard_transactions_test.go | 470 +++++++++----------- 3 files changed, 221 insertions(+), 276 deletions(-) diff --git a/go.mod b/go.mod index 4add61400..6422641fe 100644 --- a/go.mod +++ b/go.mod @@ -19,10 +19,9 @@ require ( github.com/leanovate/gopter v0.2.11 github.com/logrusorgru/aurora/v4 v4.0.0 github.com/onflow/atree v0.12.0 - github.com/onflow/cadence-standard-transactions v0.1.0 + github.com/onflow/cadence-standard-transactions v0.4.0 github.com/onflow/crypto v0.25.3 github.com/onflow/fixed-point v0.1.1 - github.com/onflow/flow-go-sdk v1.9.1 github.com/rivo/uniseg v0.4.7 github.com/schollz/progressbar/v3 v3.18.0 github.com/stretchr/testify v1.11.1 @@ -42,10 +41,7 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect - github.com/ethereum/go-ethereum v1.16.7 // indirect github.com/fxamacker/circlehash v0.3.0 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/holiman/uint256 v1.3.2 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/kr/text v0.2.0 // indirect @@ -54,8 +50,6 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-tty v0.0.3 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect - github.com/onflow/flow/protobuf/go/flow v0.4.18 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect @@ -67,7 +61,6 @@ require ( golang.org/x/sys v0.38.0 // indirect golang.org/x/term v0.37.0 // indirect gonum.org/v1/gonum v0.16.0 // indirect - google.golang.org/protobuf v1.36.10 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fc82b4c6e..0a6cba5c0 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.16.7 h1:qeM4TvbrWK0UC0tgkZ7NiRsmBGwsjqc64BHo20U59UQ= -github.com/ethereum/go-ethereum v1.16.7/go.mod h1:Fs6QebQbavneQTYcA39PEKv2+zIjX7rPUZ14DER46wk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fxamacker/cbor/v2 v2.9.1-0.20251019205732-39888e6be013 h1:jcwW+JBYGe3qgiPQ4deXaannYxVdxjMw57/dw+gcEfQ= @@ -131,8 +129,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -193,8 +189,6 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= -github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -263,22 +257,16 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/onflow/atree v0.12.0 h1:X7/UEPyCaaEQ1gCg11KDvfyEtEeQLhtRtxMHjAiH/Co= github.com/onflow/atree v0.12.0/go.mod h1:qdZcfLQwPirHcNpLiK+2t3KAo+SAb9Si6TqurE6pykE= -github.com/onflow/cadence-standard-transactions v0.1.0 h1:CuHlQgPIUeWQaaSU5w3euAvO1xUz7nzp3S5Ui8bOhPs= -github.com/onflow/cadence-standard-transactions v0.1.0/go.mod h1:C5z6Ka+Ta7zZC7uYDUhPwwS/HwrT0q3Yp6BiDba53bw= +github.com/onflow/cadence-standard-transactions v0.4.0 h1:xqwLwPAy3/fLL3UemtVQhfthRUfXSPKmTMd4ElM6Z1w= +github.com/onflow/cadence-standard-transactions v0.4.0/go.mod h1:OqwN4Pusj6Aj8M6kJhipttQ0qtOZ24ycDJwWJHy5WTA= github.com/onflow/crypto v0.25.3 h1:XQ3HtLsw8h1+pBN+NQ1JYM9mS2mVXTyg55OldaAIF7U= github.com/onflow/crypto v0.25.3/go.mod h1:+1igaXiK6Tjm9wQOBD1EGwW7bYWMUGKtwKJ/2QL/OWs= github.com/onflow/fixed-point v0.1.1 h1:j0jYZVO8VGyk1476alGudEg7XqCkeTVxb5ElRJRKS90= github.com/onflow/fixed-point v0.1.1/go.mod h1:gJdoHqKtToKdOZbvryJvDZfcpzC7d2fyWuo3ZmLtcGY= -github.com/onflow/flow-go-sdk v1.9.1 h1:e3dTnZj9UVTPwnBj9OsSr1MexdWsUs/C8Wg5VpQ1XN4= -github.com/onflow/flow-go-sdk v1.9.1/go.mod h1:CnYk7bGwcsSSF1QwALuu1MaHNMcLyofpif7SJT+Qvpg= -github.com/onflow/flow/protobuf/go/flow v0.4.18 h1:KOujA6lg9kTXCV6oK0eErD1rwRnM9taKZss3Szi+T3Q= -github.com/onflow/flow/protobuf/go/flow v0.4.18/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= @@ -734,8 +722,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/runtime/bench_standard_transactions_test.go b/runtime/bench_standard_transactions_test.go index 00bb98fbe..56d14b31c 100644 --- a/runtime/bench_standard_transactions_test.go +++ b/runtime/bench_standard_transactions_test.go @@ -19,14 +19,10 @@ package runtime_test import ( - "crypto/rand" "encoding/binary" - "encoding/hex" "fmt" "testing" - flowsdk "github.com/onflow/flow-go-sdk" - "github.com/onflow/flow-go-sdk/crypto" "github.com/stretchr/testify/require" "github.com/onflow/cadence-standard-transactions/transactions" @@ -254,66 +250,31 @@ func createTransaction(name string, imports string, prepare string, setup string } func init() { - // create key transactions - createKeyECDSAP256Transaction, err := transactions.CreateKeyECDSAP256Transaction(100) - if err != nil { - panic(err) - } - createKeyECDSAsecp256k1Transaction, err := transactions.CreateKeyECDSAsecp256k1Transaction(100) - if err != nil { - panic(err) - } - createKeyBLSBLS12381Transaction, err := transactions.CreateKeyBLSBLS12381Transaction(100) - if err != nil { - panic(err) - } + // placeholder hex-encoded zero value + placeholderHexValue := "0000000000000000000000000000000000000000000000000000000000000000" // verify signature transaction numKeys := uint64(15) message := []byte("hello world") rawKeys := make([]string, numKeys) - signers := make([]crypto.Signer, numKeys) signatures := make([]string, numKeys) for i := 0; i < int(numKeys); i++ { - seed := make([]byte, crypto.MinSeedLength) - _, err := rand.Read(seed) - if err != nil { - panic(fmt.Errorf("failed to generate seed: %w", err)) - } - - privateKey, err := crypto.GeneratePrivateKey(crypto.ECDSA_P256, seed) - if err != nil { - panic(fmt.Errorf("failed to generate private key: %w", err)) - } - rawKeys[i] = hex.EncodeToString(privateKey.PublicKey().Encode()) - sig, err := crypto.NewInMemorySigner(privateKey, crypto.SHA3_256) - if err != nil { - panic(fmt.Errorf("failed to generate signer: %w", err)) - } - signers[i] = sig + rawKeys[i] = placeholderHexValue + signatures[i] = placeholderHexValue } - for i := 0; i < int(numKeys); i++ { - sig, err := flowsdk.SignUserMessage(signers[i], message) - if err != nil { - panic(fmt.Errorf("failed to sign message: %w", err)) - } - signatures[i] = hex.EncodeToString(sig) - } verifySignatureTransaction := transactions.VerifySignatureTransaction(numKeys, message, rawKeys, signatures) // bls - blsAggregateKeysTransaction, err := transactions.AggregateBLSAggregateKeysTransaction(42) - if err != nil { - panic(err) - } - - blsVerifyProofOfPossessionTransaction, err := transactions.BLSVerifyProofOfPossessionTransaction(8) - if err != nil { - panic(err) + numBLSKeys := 42 + pks := make([]string, numBLSKeys) + for i := 0; i < numBLSKeys; i++ { + pks[i] = placeholderHexValue } + blsAggregateKeysTransaction := transactions.AggregateBLSAggregateKeysTransaction(numBLSKeys, pks) + blsVerifyProofOfPossessionTransaction := transactions.BLSVerifyProofOfPossessionTransaction(8, placeholderHexValue, placeholderHexValue) testTransactions = []Transaction{ createTransaction( @@ -595,19 +556,19 @@ func init() { createTransaction( "CreateKeyECDSAP256", "", - createKeyECDSAP256Transaction.GetPrepareBlock(), + transactions.CreateKeyECDSAP256Transaction(100, placeholderHexValue).GetPrepareBlock(), "", ), createTransaction( "CreateKeyECDSAsecp256k1", "", - createKeyECDSAsecp256k1Transaction.GetPrepareBlock(), + transactions.CreateKeyECDSAsecp256k1Transaction(100, placeholderHexValue).GetPrepareBlock(), "", ), createTransaction( "CreateKeyBLSBLS12381", "", - createKeyBLSBLS12381Transaction.GetPrepareBlock(), + transactions.CreateKeyBLSBLS12381Transaction(100, placeholderHexValue).GetPrepareBlock(), "", ), createTransaction( @@ -697,167 +658,170 @@ func init() { } } -func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { - contractsAddress := common.MustBytesToAddress([]byte{0x1}) - senderAddress := common.MustBytesToAddress([]byte{0x2}) - receiverAddress := common.MustBytesToAddress([]byte{0x3}) - - var signerAccount common.Address - - var environment Environment - if useVM { - environment = NewBaseVMEnvironment(Config{}) - } else { - environment = NewBaseInterpreterEnvironment(Config{}) - } - - // Helper function to create a fresh runtime interface with isolated storage - createRuntimeInterface := func() *TestRuntimeInterface { - accountCodes := map[common.Location][]byte{} - accountCounter := uint64(4) - created := false - signerAccount = contractsAddress - - return &TestRuntimeInterface{ - OnGetCode: func(location common.Location) (bytes []byte, err error) { - return accountCodes[location], nil - }, - Storage: NewTestLedger(nil, nil), - OnGetSigningAccounts: func() ([]common.Address, error) { - return []common.Address{signerAccount}, nil - }, - OnResolveLocation: NewSingleIdentifierLocationResolver(b), - OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { - return accountCodes[location], nil - }, - OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { - accountCodes[location] = code - return nil - }, - OnEmitEvent: func(event cadence.Event) error { - return nil - }, - OnDecodeArgument: func(b []byte, t cadence.Type) (value cadence.Value, err error) { - return json.Decode(nil, b) - }, - OnGetAccountBalance: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnGetAccountAvailableBalance: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnGetStorageUsed: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnGetStorageCapacity: func(address common.Address) (uint64, error) { - return 0, nil - }, - OnCreateAccount: func(payer Address) (address Address, err error) { - accountCounter++ - addressBytes := make([]byte, 8) - binary.BigEndian.PutUint64(addressBytes, accountCounter) - result := interpreter.NewUnmeteredAddressValueFromBytes(addressBytes) - return result.ToAddress(), nil - }, - OnValidatePublicKey: func(key *stdlib.PublicKey) error { - return nil - }, - OnVerifySignature: func( - signature []byte, - tag string, - signedData []byte, - publicKey []byte, - signatureAlgorithm SignatureAlgorithm, - hashAlgorithm HashAlgorithm, - ) (bool, error) { - return true, nil - }, - OnHash: func(data []byte, tag string, hashAlgorithm HashAlgorithm) ([]byte, error) { - return data, nil - }, - OnBLSVerifyPOP: func(pk *stdlib.PublicKey, s []byte) (bool, error) { - return true, nil - }, - OnBLSAggregateSignatures: func(sigs [][]byte) ([]byte, error) { - if len(sigs) == 0 { - return nil, fmt.Errorf("no signatures to aggregate") - } - return sigs[0], nil - }, - OnBLSAggregatePublicKeys: func(keys []*stdlib.PublicKey) (*stdlib.PublicKey, error) { - if len(keys) == 0 { - return nil, fmt.Errorf("no keys to aggregate") - } - return keys[0], nil - }, - OnAddAccountKey: func(address Address, publicKey *stdlib.PublicKey, hashAlgo HashAlgorithm, weight int) (*stdlib.AccountKey, error) { - return &stdlib.AccountKey{PublicKey: publicKey, HashAlgo: hashAlgo, Weight: weight}, nil - }, - OnGetAccountKey: func(address Address, index uint32) (*stdlib.AccountKey, error) { - return &stdlib.AccountKey{KeyIndex: index, PublicKey: &stdlib.PublicKey{}}, nil - }, - OnRemoveAccountKey: func(address Address, index uint32) (*stdlib.AccountKey, error) { - return &stdlib.AccountKey{KeyIndex: index, PublicKey: &stdlib.PublicKey{}}, nil - }, - OnAccountKeysCount: func(address Address) (uint32, error) { - return 1, nil - }, - OnGetAccountContractNames: func(address Address) ([]string, error) { - if created { - // ensures GetContractsTransaction only creates the contracts once - return []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"}, nil - } - created = true - return []string{}, nil - }, - } +func createRuntimeInterface(b *testing.B, signerAccount *common.Address, contractsAddress *common.Address) *TestRuntimeInterface { + accountCodes := map[common.Location][]byte{} + accountCounter := uint64(4) + created := false + *signerAccount = *contractsAddress + + return &TestRuntimeInterface{ + OnGetCode: func(location common.Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]common.Address, error) { + return []common.Address{*signerAccount}, nil + }, + OnResolveLocation: NewSingleIdentifierLocationResolver(b), + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnEmitEvent: func(event cadence.Event) error { + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (value cadence.Value, err error) { + return json.Decode(nil, b) + }, + OnGetAccountBalance: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetAccountAvailableBalance: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetStorageUsed: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnGetStorageCapacity: func(address common.Address) (uint64, error) { + return 0, nil + }, + OnCreateAccount: func(payer Address) (address Address, err error) { + accountCounter++ + addressBytes := make([]byte, 8) + binary.BigEndian.PutUint64(addressBytes, accountCounter) + result := interpreter.NewUnmeteredAddressValueFromBytes(addressBytes) + return result.ToAddress(), nil + }, + OnValidatePublicKey: func(key *stdlib.PublicKey) error { + return nil + }, + OnVerifySignature: func( + signature []byte, + tag string, + signedData []byte, + publicKey []byte, + signatureAlgorithm SignatureAlgorithm, + hashAlgorithm HashAlgorithm, + ) (bool, error) { + return true, nil + }, + OnHash: func(data []byte, tag string, hashAlgorithm HashAlgorithm) ([]byte, error) { + return data, nil + }, + OnBLSVerifyPOP: func(pk *stdlib.PublicKey, s []byte) (bool, error) { + return true, nil + }, + OnBLSAggregateSignatures: func(sigs [][]byte) ([]byte, error) { + if len(sigs) == 0 { + return nil, fmt.Errorf("no signatures to aggregate") + } + return sigs[0], nil + }, + OnBLSAggregatePublicKeys: func(keys []*stdlib.PublicKey) (*stdlib.PublicKey, error) { + if len(keys) == 0 { + return nil, fmt.Errorf("no keys to aggregate") + } + return keys[0], nil + }, + OnAddAccountKey: func(address Address, publicKey *stdlib.PublicKey, hashAlgo HashAlgorithm, weight int) (*stdlib.AccountKey, error) { + return &stdlib.AccountKey{PublicKey: publicKey, HashAlgo: hashAlgo, Weight: weight}, nil + }, + OnGetAccountKey: func(address Address, index uint32) (*stdlib.AccountKey, error) { + return &stdlib.AccountKey{KeyIndex: index, PublicKey: &stdlib.PublicKey{}}, nil + }, + OnRemoveAccountKey: func(address Address, index uint32) (*stdlib.AccountKey, error) { + return &stdlib.AccountKey{KeyIndex: index, PublicKey: &stdlib.PublicKey{}}, nil + }, + OnAccountKeysCount: func(address Address) (uint32, error) { + return 1, nil + }, + OnGetAccountContractNames: func(address Address) ([]string, error) { + if created { + // ensures GetContractsTransaction only creates the contracts once + return []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"}, nil + } + created = true + return []string{}, nil + }, } +} - // Helper function to setup a fresh runtime with contracts deployed - setupRuntime := func(b *testing.B) (TestRuntime, func() common.TransactionLocation, *TestRuntimeInterface) { - - runtimeInterface := createRuntimeInterface() - signerAccount = contractsAddress - - runtime := NewTestRuntime() - nextTransactionLocation := NewTransactionLocationGenerator() +func setupRuntime(b *testing.B, signerAccount *common.Address, contractsAddress *common.Address, senderAddress *common.Address, receiverAddress *common.Address, environment Environment, useVM bool) (TestRuntime, func() common.TransactionLocation, *TestRuntimeInterface) { + runtimeInterface := createRuntimeInterface(b, signerAccount, contractsAddress) + *signerAccount = *contractsAddress - // Deploy Fungible Token contract - err := runtime.ExecuteTransaction( - Script{ - Source: DeploymentTransaction( - "FungibleToken", - []byte(modifiedFungibleTokenContractInterface), - ), - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) + runtime := NewTestRuntime() + nextTransactionLocation := NewTransactionLocationGenerator() - // Deploy Flow Token contract - err = runtime.ExecuteTransaction( - Script{ - Source: DeploymentTransaction("FlowToken", []byte(modifiedFlowContract)), - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) + // Deploy Fungible Token contract + err := runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction( + "FungibleToken", + []byte(modifiedFungibleTokenContractInterface), + ), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Deploy Flow Token contract + err = runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction("FlowToken", []byte(modifiedFlowContract)), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Deploy Crypto contract + err = runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction("Crypto", []byte(realCryptoContract)), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Setup both user accounts for Flow Token + for _, address := range []common.Address{ + *senderAddress, + *receiverAddress, + } { + *signerAccount = address - // Deploy Crypto contract err = runtime.ExecuteTransaction( Script{ - Source: DeploymentTransaction("Crypto", []byte(realCryptoContract)), + Source: []byte(realSetupFlowTokenAccountTransaction), }, Context{ Interface: runtimeInterface, @@ -867,62 +831,64 @@ func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { }, ) require.NoError(b, err) + } - // Setup both user accounts for Flow Token - for _, address := range []common.Address{ - senderAddress, - receiverAddress, - } { - signerAccount = address - - err = runtime.ExecuteTransaction( - Script{ - Source: []byte(realSetupFlowTokenAccountTransaction), - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) - } - - // Mint 1000 FLOW to sender - mintAmount, err := cadence.NewUFix64("100000000000.0") - require.NoError(b, err) - - signerAccount = contractsAddress + // Mint 1000 FLOW to sender + mintAmount, err := cadence.NewUFix64("100000000000.0") + require.NoError(b, err) + + *signerAccount = *contractsAddress + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(realMintFlowTokenTransaction), + Arguments: encodeArgs([]cadence.Value{ + cadence.Address(*senderAddress), + mintAmount, + }), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + Environment: environment, + UseVM: useVM, + }, + ) + require.NoError(b, err) + + // Set signer account to sender for benchmark transactions + *signerAccount = *senderAddress + + return runtime, nextTransactionLocation, runtimeInterface +} - err = runtime.ExecuteTransaction( - Script{ - Source: []byte(realMintFlowTokenTransaction), - Arguments: encodeArgs([]cadence.Value{ - cadence.Address(senderAddress), - mintAmount, - }), - }, - Context{ - Interface: runtimeInterface, - Location: nextTransactionLocation(), - Environment: environment, - UseVM: useVM, - }, - ) - require.NoError(b, err) +func benchmarkRuntimeTransactions(b *testing.B, useVM bool) { + contractsAddress := common.MustBytesToAddress([]byte{0x1}) + senderAddress := common.MustBytesToAddress([]byte{0x2}) + receiverAddress := common.MustBytesToAddress([]byte{0x3}) - // Set signer account to sender for benchmark transactions - signerAccount = senderAddress + var signerAccount common.Address - return runtime, nextTransactionLocation, runtimeInterface + var environment Environment + if useVM { + environment = NewBaseVMEnvironment(Config{}) + } else { + environment = NewBaseInterpreterEnvironment(Config{}) } for _, transaction := range testTransactions { b.Run(transaction.Name, func(b *testing.B) { // Create fresh runtime and storage for this sub-benchmark - runtime, nextTransactionLocation, runtimeInterface := setupRuntime() + runtime, nextTransactionLocation, runtimeInterface := setupRuntime( + b, + &signerAccount, + &contractsAddress, + &senderAddress, + &receiverAddress, + environment, + useVM, + ) for b.Loop() { b.StopTimer()