From b8451c7e598a2cd2f37742089e4b4cfb667dc324 Mon Sep 17 00:00:00 2001 From: Alok Date: Sat, 3 Feb 2024 18:38:53 +0530 Subject: [PATCH 1/3] feat: add settler tests --- go.mod | 57 ++++-- go.sum | 163 ++++++++++++--- pkg/settler/settler.go | 89 ++++++-- pkg/settler/settler_test.go | 301 +++++++++++++++++++++++++++ pkg/store/store.go | 101 +++++++--- pkg/store/store_test.go | 392 ++++++++++++++++++++++++++++++++++++ pkg/updater/metrics.go | 18 +- pkg/updater/updater.go | 62 +++--- pkg/updater/updater_test.go | 60 ++++-- 9 files changed, 1119 insertions(+), 124 deletions(-) create mode 100644 pkg/settler/settler_test.go create mode 100644 pkg/store/store_test.go diff --git a/go.mod b/go.mod index 8427c3d..58dc11b 100644 --- a/go.mod +++ b/go.mod @@ -4,61 +4,94 @@ go 1.21.1 require ( github.com/ethereum/go-ethereum v1.13.5 + github.com/google/go-cmp v0.6.0 github.com/lib/pq v1.10.9 - github.com/primevprotocol/contracts-abi v0.1.2 + github.com/primevprotocol/contracts-abi v0.1.3-0.20240131094253-30834a4dec8d github.com/prometheus/client_golang v1.14.0 github.com/rs/zerolog v1.31.0 + github.com/testcontainers/testcontainers-go v0.27.0 github.com/urfave/cli/v2 v2.27.1 - golang.org/x/crypto v0.14.0 + golang.org/x/crypto v0.18.0 gopkg.in/yaml.v2 v2.4.0 ) require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/containerd/containerd v1.7.11 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v24.0.7+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/holiman/uint256 v1.2.3 // indirect + github.com/klauspost/compress v1.17.5 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect + github.com/opencontainers/runc v1.1.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rivo/uniseg v0.4.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/shirou/gopsutil/v3 v3.23.11 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/supranational/blst v0.3.11 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tklauser/go-sysconf v0.3.13 // indirect + github.com/tklauser/numcpus v0.7.0 // indirect github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.13.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect golang.org/x/time v0.4.0 // indirect - golang.org/x/tools v0.13.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + golang.org/x/tools v0.17.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.32.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index a7e798c..6397e67 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,11 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= @@ -8,6 +14,8 @@ github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwS github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= @@ -24,11 +32,15 @@ github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPx github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= @@ -48,16 +60,28 @@ github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/Yj github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= +github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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= @@ -69,6 +93,15 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -84,6 +117,7 @@ github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -99,14 +133,16 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclK github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -144,15 +180,18 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -193,10 +232,11 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= +github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -212,7 +252,11 @@ github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -242,11 +286,21 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -256,6 +310,14 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -264,8 +326,10 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/primevprotocol/contracts-abi v0.1.2 h1:Q1xWCUHjH1B/f/d3Egwf9BVt4iutw/QHInXI6CAr8Wk= -github.com/primevprotocol/contracts-abi v0.1.2/go.mod h1:dE2KkvEqC+itvPa3SCrqQfvH5Hfnfn6omNRwWDTdIp8= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/primevprotocol/contracts-abi v0.1.3-0.20240131094253-30834a4dec8d h1:9Yg8SxGPvE6eAffiCXEGFZYIkYaWTnaHW7cBjUEWhp4= +github.com/primevprotocol/contracts-abi v0.1.3-0.20240131094253-30834a4dec8d/go.mod h1:dE2KkvEqC+itvPa3SCrqQfvH5Hfnfn6omNRwWDTdIp8= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -288,14 +352,25 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= +github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +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/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= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -307,27 +382,37 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/testcontainers/testcontainers-go v0.27.0 h1:IeIrJN4twonTDuMuBNQdKZ+K97yd7VrmNGu+lDpYcDk= +github.com/testcontainers/testcontainers-go v0.27.0/go.mod h1:+HgYZcd17GshBUZv9b+jKFJ198heWPQq3KQIp2+N+7U= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= +github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= +github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= @@ -336,6 +421,8 @@ github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBn github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -349,6 +436,8 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -357,11 +446,11 @@ golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +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/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -370,8 +459,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -386,9 +475,12 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -398,38 +490,50 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -437,8 +541,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= @@ -455,8 +559,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -468,12 +572,16 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= 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= @@ -485,8 +593,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -510,6 +619,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/pkg/settler/settler.go b/pkg/settler/settler.go index dcda472..6705729 100644 --- a/pkg/settler/settler.go +++ b/pkg/settler/settler.go @@ -16,6 +16,15 @@ import ( var ( allowedPendingTxnCount = 128 + batchSize = 10 +) + +type SettlementType string + +const ( + SettlementTypeReward SettlementType = "reward" + SettlementTypeSlash SettlementType = "slash" + SettlementTypeReturn SettlementType = "return" ) type Settlement struct { @@ -23,14 +32,15 @@ type Settlement struct { TxHash string BlockNum int64 Builder string - IsSlash bool + Amount uint64 + Type SettlementType } type SettlerRegister interface { LastNonce() (int64, error) PendingTxnCount() (int, error) SubscribeSettlements(ctx context.Context) <-chan Settlement - SettlementInitiated(ctx context.Context, commitmentIdx []byte, txHash common.Hash, nonce uint64) error + SettlementInitiated(ctx context.Context, commitmentIdx [][]byte, txHash common.Hash, nonce uint64) error MarkSettlementComplete(ctx context.Context, nonce uint64) (int, error) } @@ -42,10 +52,13 @@ type Oracle interface { builder string, isSlash bool, ) (*types.Transaction, error) + UnlockFunds(opts *bind.TransactOpts, bidIDs [][32]byte) (*types.Transaction, error) } type Transactor interface { - bind.ContractTransactor + PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) + SuggestGasPrice(ctx context.Context) (*big.Int, error) + SuggestGasTipCap(ctx context.Context) (*big.Int, error) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) BlockNumber(ctx context.Context) (uint64, error) } @@ -179,6 +192,7 @@ func (s *Settler) Start(ctx context.Context) <-chan struct{} { RESTART: cctx, unsub := context.WithCancel(ctx) settlementChan := s.settlerRegister.SubscribeSettlements(cctx) + returns := make([][32]byte, 0, batchSize) for { select { @@ -202,28 +216,65 @@ func (s *Settler) Start(ctx context.Context) <-chan struct{} { return errors.New("too many pending txns") } - opts, err := s.getTransactOpts(ctx) - if err != nil { - return err + var ( + commitmentIdx [32]byte + commitmentIndexes [][]byte + commitmentPostingTxn *types.Transaction + opts *bind.TransactOpts + ) + + // if we are batching returns, we don't want to post the txn until we have a full batch + if settlement.Type != SettlementTypeReturn || len(returns) == batchSize-1 { + opts, err = s.getTransactOpts(ctx) + if err != nil { + return err + } } - var commitmentIdx [32]byte copy(commitmentIdx[:], settlement.CommitmentIdx) - commitmentPostingTxn, err := s.rollupClient.ProcessBuilderCommitmentForBlockNumber( - opts, - commitmentIdx, - big.NewInt(settlement.BlockNum), - settlement.Builder, - settlement.IsSlash, - ) - if err != nil { - return err + switch settlement.Type { + case SettlementTypeReward: + fallthrough + case SettlementTypeSlash: + commitmentPostingTxn, err = s.rollupClient.ProcessBuilderCommitmentForBlockNumber( + opts, + commitmentIdx, + big.NewInt(settlement.BlockNum), + settlement.Builder, + settlement.Type == SettlementTypeSlash, + ) + if err != nil { + return err + } + commitmentIndexes = [][]byte{commitmentIdx[:]} + case SettlementTypeReturn: + returns = append(returns, commitmentIdx) + if len(returns) == batchSize { + commitmentPostingTxn, err = s.rollupClient.UnlockFunds( + opts, + returns, + ) + if err != nil { + return err + } + for _, idx := range returns { + commitmentIndexes = append(commitmentIndexes, idx[:]) + } + // reset batch + returns = returns[:0] + } + } + + if commitmentPostingTxn == nil { + // if we are batching returns, we don't want to post the txn + // until we have a full batch + return nil } err = s.settlerRegister.SettlementInitiated( ctx, - settlement.CommitmentIdx, + commitmentIndexes, commitmentPostingTxn.Hash(), commitmentPostingTxn.Nonce(), ) @@ -231,6 +282,8 @@ func (s *Settler) Start(ctx context.Context) <-chan struct{} { return err } + commitmentIndexes = commitmentIndexes[:0] + s.metrics.LastUsedNonce.Set(float64(commitmentPostingTxn.Nonce())) s.metrics.SettlementsPostedCount.Inc() s.metrics.CurrentSettlementL1Block.Set(float64(settlement.BlockNum)) @@ -239,7 +292,7 @@ func (s *Settler) Start(ctx context.Context) <-chan struct{} { Int64("blockNum", settlement.BlockNum). Str("txHash", commitmentPostingTxn.Hash().Hex()). Str("builder", settlement.Builder). - Bool("isSlash", settlement.IsSlash). + Str("settlementType", string(settlement.Type)). Msg("builder commitment processed") return nil diff --git a/pkg/settler/settler_test.go b/pkg/settler/settler_test.go new file mode 100644 index 0000000..45f0010 --- /dev/null +++ b/pkg/settler/settler_test.go @@ -0,0 +1,301 @@ +package settler_test + +import ( + "context" + "crypto/ecdsa" + "fmt" + "math/big" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/primevprotocol/mev-oracle/pkg/settler" +) + +type testRegister struct { + currentNonce atomic.Int64 + pendingTxns atomic.Int32 + settlementChan chan settler.Settlement + mu sync.Mutex + settlementsInitiated [][]byte + settlementsCompleted atomic.Int32 +} + +func (t *testRegister) LastNonce() (int64, error) { + return t.currentNonce.Load(), nil +} + +func (t *testRegister) PendingTxnCount() (int, error) { + return int(t.pendingTxns.Load()), nil +} + +func (t *testRegister) SubscribeSettlements(ctx context.Context) <-chan settler.Settlement { + sc := make(chan settler.Settlement) + go func() { + for { + select { + case <-ctx.Done(): + return + case s := <-t.settlementChan: + sc <- s + } + } + }() + + return sc +} + +func (t *testRegister) SettlementInitiated(ctx context.Context, commitmentIdx [][]byte, txHash common.Hash, nonce uint64) error { + t.mu.Lock() + defer t.mu.Unlock() + + t.settlementsInitiated = append(t.settlementsInitiated, commitmentIdx...) + return nil +} + +func (t *testRegister) MarkSettlementComplete(ctx context.Context, nonce uint64) (int, error) { + t.settlementsCompleted.Store(int32(nonce)) + return 1, nil +} + +func (t *testRegister) settlementsInitiatedCount() int { + t.mu.Lock() + defer t.mu.Unlock() + + return len(t.settlementsInitiated) +} + +type testOracle struct { + key *ecdsa.PrivateKey + mu sync.Mutex + commitmentIdxs [][32]byte + bidIDs [][32]byte + slashCount atomic.Int32 + rewardCount atomic.Int32 +} + +func (t *testOracle) ProcessBuilderCommitmentForBlockNumber( + opts *bind.TransactOpts, + commitmentIdx [32]byte, + blockNum *big.Int, + builder string, + isSlash bool, +) (*types.Transaction, error) { + t.mu.Lock() + defer t.mu.Unlock() + + if isSlash { + t.slashCount.Add(1) + } else { + t.rewardCount.Add(1) + } + + t.commitmentIdxs = append(t.commitmentIdxs, commitmentIdx) + return types.MustSignNewTx( + t.key, + types.NewLondonSigner(big.NewInt(1)), + &types.DynamicFeeTx{ + Nonce: opts.Nonce.Uint64(), + GasTipCap: opts.GasTipCap, + GasFeeCap: opts.GasFeeCap, + }, + ), nil +} + +func (t *testOracle) UnlockFunds(opts *bind.TransactOpts, bidIDs [][32]byte) (*types.Transaction, error) { + t.mu.Lock() + defer t.mu.Unlock() + + t.bidIDs = append(t.bidIDs, bidIDs...) + return types.MustSignNewTx( + t.key, + types.NewLondonSigner(big.NewInt(1)), + &types.DynamicFeeTx{ + Nonce: opts.Nonce.Uint64(), + GasTipCap: opts.GasTipCap, + GasFeeCap: opts.GasFeeCap, + }, + ), nil +} + +func (t *testOracle) commitmentIdxsCount() int { + t.mu.Lock() + defer t.mu.Unlock() + + return len(t.commitmentIdxs) +} + +func (t *testOracle) bidIDsCount() int { + t.mu.Lock() + defer t.mu.Unlock() + + return len(t.bidIDs) +} + +type testTransactor struct { + currentNonce atomic.Uint64 + currentBlockNumber atomic.Uint64 +} + +func (t *testTransactor) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + return t.currentNonce.Load() + 1, nil +} + +func (t *testTransactor) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + return big.NewInt(1000), nil +} + +func (t *testTransactor) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + return big.NewInt(1000), nil +} + +func (t *testTransactor) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { + return t.currentNonce.Load(), nil +} + +func (t *testTransactor) BlockNumber(ctx context.Context) (uint64, error) { + return t.currentBlockNumber.Load(), nil +} + +func waitForCount(dur time.Duration, expected int, f func() int) error { + start := time.Now() + for { + if f() == expected { + return nil + } + time.Sleep(100 * time.Millisecond) + if time.Since(start) > dur { + return fmt.Errorf("expected count %d, got %d", expected, f()) + } + } +} + +func TestSettler(t *testing.T) { + t.Parallel() + + key, err := crypto.GenerateKey() + if err != nil { + t.Fatal(err) + } + + ownerAddr := common.HexToAddress("0xabcd") + + orcl := &testOracle{key: key} + reg := &testRegister{ + settlementChan: make(chan settler.Settlement), + } + transactor := &testTransactor{} + + s := settler.NewSettler( + key, + big.NewInt(1000), + ownerAddr, + orcl, + reg, + transactor, + ) + + ctx, cancel := context.WithCancel(context.Background()) + done := s.Start(ctx) + + // Test that the settler is able to process a settlement + for i := 0; i < 10; i++ { + var sType settler.SettlementType + if i%2 == 0 { + sType = settler.SettlementTypeReward + } else { + sType = settler.SettlementTypeSlash + } + reg.settlementChan <- settler.Settlement{ + CommitmentIdx: big.NewInt(int64(i + 1)).Bytes(), + TxHash: "0x1234", + BlockNum: 100, + Builder: "0x1234", + Amount: 1000, + Type: sType, + } + + if err := waitForCount(5*time.Second, i+1, orcl.commitmentIdxsCount); err != nil { + t.Fatal(err) + } + + if err := waitForCount(5*time.Second, i+1, reg.settlementsInitiatedCount); err != nil { + t.Fatal(err) + } + + reg.currentNonce.Add(1) + } + + if reg.settlementsCompleted.Load() != 0 { + t.Fatalf("expected 0 settlements completed, got %d", reg.settlementsCompleted.Load()) + } + + if orcl.slashCount.Load() != 5 { + t.Fatalf("expected 5 slashes, got %d", orcl.slashCount.Load()) + } + + if orcl.rewardCount.Load() != 5 { + t.Fatalf("expected 5 rewards, got %d", orcl.rewardCount.Load()) + } + + transactor.currentNonce.Store(10) + transactor.currentBlockNumber.Store(1) + + if err := waitForCount(5*time.Second, 10, func() int { + return int(reg.settlementsCompleted.Load()) + }); err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + reg.settlementChan <- settler.Settlement{ + CommitmentIdx: big.NewInt(int64(i + 1)).Bytes(), + TxHash: "0x1234", + BlockNum: 100, + Builder: "0x1234", + Amount: 1000, + Type: settler.SettlementTypeReturn, + } + } + + if err := waitForCount(5*time.Second, 20, reg.settlementsInitiatedCount); err != nil { + t.Fatal(err) + } + + if err := waitForCount(5*time.Second, 10, orcl.bidIDsCount); err != nil { + t.Fatal(err) + } + + transactor.currentNonce.Store(11) + transactor.currentBlockNumber.Store(2) + + if err := waitForCount(5*time.Second, 11, func() int { + return int(reg.settlementsCompleted.Load()) + }); err != nil { + t.Fatal(err) + } + + reg.pendingTxns.Store(129) + + reg.settlementChan <- settler.Settlement{ + CommitmentIdx: big.NewInt(11).Bytes(), + TxHash: "0x1234", + BlockNum: 100, + Builder: "0x1234", + Amount: 1000, + Type: settler.SettlementTypeReward, + } + + time.Sleep(2 * time.Second) + if reg.settlementsInitiatedCount() != 20 { + t.Fatalf("expected 20 settlements initiated, got %d", reg.settlementsInitiatedCount()) + } + + cancel() + <-done +} diff --git a/pkg/store/store.go b/pkg/store/store.go index 12a6802..85c760e 100644 --- a/pkg/store/store.go +++ b/pkg/store/store.go @@ -3,22 +3,33 @@ package store import ( "context" "database/sql" + "fmt" + "strings" "github.com/ethereum/go-ethereum/common" + "github.com/lib/pq" _ "github.com/lib/pq" "github.com/primevprotocol/mev-oracle/pkg/settler" "github.com/primevprotocol/mev-oracle/pkg/updater" ) +var settlementType = ` +DO $$ BEGIN + CREATE TYPE settlement_type AS ENUM ('reward', 'slash', 'return'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$;` + var settlementsTable = ` CREATE TABLE IF NOT EXISTS settlements ( commitment_index BYTEA PRIMARY KEY, transaction TEXT, block_number BIGINT, builder_address BYTEA, - is_slash BOOLEAN, - nonce BIGINT, + type settlement_type, + amount NUMERIC(24, 0), chainhash BYTEA, + nonce BIGINT, settled BOOLEAN );` @@ -36,14 +47,11 @@ type Store struct { } func NewStore(db *sql.DB) (*Store, error) { - _, err := db.Exec(settlementsTable) - if err != nil { - return nil, err - } - - _, err = db.Exec(winnersTable) - if err != nil { - return nil, err + for _, table := range []string{settlementType, settlementsTable, winnersTable} { + _, err := db.Exec(table) + if err != nil { + return nil, err + } } return &Store{ @@ -134,14 +142,44 @@ func (s *Store) AddSettlement( commitmentIdx []byte, txHash string, blockNum int64, + amount uint64, builder string, - isSlash bool, + settlementType settler.SettlementType, ) error { - insertStr := ` - INSERT INTO settlements (commitment_index, transaction, block_number, builder_address, is_slash, nonce, chainhash, settled) - VALUES ($1, $2, $3, $4, $5, 0, NULL, false)` + columns := []string{ + "commitment_index", + "transaction", + "block_number", + "builder_address", + "type", + "amount", + "settled", + "chainhash", + "nonce", + } + values := []interface{}{ + commitmentIdx, + txHash, + blockNum, + builder, + settlementType, + amount, + false, + nil, + 0, + } + placeholder := make([]string, len(values)) + for i := range columns { + placeholder[i] = fmt.Sprintf("$%d", i+1) + } - _, err := s.db.ExecContext(ctx, insertStr, commitmentIdx, txHash, blockNum, builder, isSlash) + insertStr := fmt.Sprintf( + "INSERT INTO settlements (%s) VALUES (%s)", + strings.Join(columns, ", "), + strings.Join(placeholder, ", "), + ) + + _, err := s.db.ExecContext(ctx, insertStr, values...) if err != nil { return err } @@ -157,9 +195,10 @@ func (s *Store) SubscribeSettlements(ctx context.Context) <-chan settler.Settlem RETRY: for { queryStr := ` - SELECT commitment_index, transaction, block_number, builder_address, is_slash + SELECT commitment_index, transaction, block_number, builder_address, amount, type FROM settlements WHERE settled = false AND chainhash IS NULL` + results, err := s.db.QueryContext(ctx, queryStr) if err != nil { return @@ -173,7 +212,8 @@ func (s *Store) SubscribeSettlements(ctx context.Context) <-chan settler.Settlem &s.TxHash, &s.BlockNum, &s.Builder, - &s.IsSlash, + &s.Amount, + &s.Type, ) if err != nil { continue RETRY @@ -199,16 +239,16 @@ func (s *Store) SubscribeSettlements(ctx context.Context) <-chan settler.Settlem func (s *Store) SettlementInitiated( ctx context.Context, - commitmentIdx []byte, + commitmentIndexes [][]byte, txHash common.Hash, nonce uint64, ) error { _, err := s.db.ExecContext( ctx, - "UPDATE settlements SET chainhash = $1, nonce = $2 WHERE commitment_index = $3", + "UPDATE settlements SET chainhash = $1, nonce = $2 WHERE commitment_index = ANY($3::BYTEA[])", txHash.Bytes(), nonce, - commitmentIdx, + pq.Array(commitmentIndexes), ) if err != nil { return err @@ -244,7 +284,7 @@ func (s *Store) LastNonce() (int64, error) { func (s *Store) PendingTxnCount() (int, error) { var count int err := s.db.QueryRow( - "SELECT COUNT(*) FROM settlements WHERE chainhash IS NOT NULL AND settled = false", + "SELECT COUNT(DISTINCT chainhash) FROM settlements WHERE chainhash IS NOT NULL AND settled = false", ).Scan(&count) if err != nil { return 0, err @@ -256,7 +296,11 @@ type BlockInfo struct { BlockNumber int64 Builder string NoOfCommitments int + TotalAmount int + NoOfRewards int + TotalRewards int NoOfSlashes int + TotalSlashes int NoOfSettlements int } @@ -267,7 +311,11 @@ func (s *Store) ProcessedBlocks(limit, offset int) ([]BlockInfo, error) { winners.block_number, winners.builder_address, COUNT(settlements.commitment_index) AS commitment_count, - COUNT(settlements.is_slash) AS slash_count, + SUM(settlements.amount) AS total_amount, + COUNT(settlements.type = 'reward' OR NULL) AS reward_count, + SUM(settlements.amount) FILTER (WHERE settlements.type = 'reward') AS total_rewards, + COUNT(settlements.type = 'slash' OR NULL) AS slash_count, + SUM(settlements.amount) FILTER (WHERE settlements.type = 'slash') AS total_slashes, COUNT(settlements.settled) AS settled_count FROM winners @@ -293,7 +341,11 @@ func (s *Store) ProcessedBlocks(limit, offset int) ([]BlockInfo, error) { &b.BlockNumber, &b.Builder, &b.NoOfCommitments, + &b.TotalAmount, + &b.NoOfRewards, + &b.TotalRewards, &b.NoOfSlashes, + &b.TotalSlashes, &b.NoOfSettlements, ) if err != nil { @@ -306,6 +358,7 @@ func (s *Store) ProcessedBlocks(limit, offset int) ([]BlockInfo, error) { type CommitmentStats struct { TotalCount int + RewardCount int SlashCount int SettlementsCompletedCount int } @@ -315,12 +368,14 @@ func (s *Store) CommitmentStats() (CommitmentStats, error) { err := s.db.QueryRow(` SELECT COUNT(*), - COUNT(is_slash), + COUNT(type = 'reward' OR NULL), + COUNT(type = 'slash' OR NULL), COUNT(settled) FROM settlements `).Scan( &stats.TotalCount, + &stats.RewardCount, &stats.SlashCount, &stats.SettlementsCompletedCount, ) diff --git a/pkg/store/store_test.go b/pkg/store/store_test.go new file mode 100644 index 0000000..3bb1ad6 --- /dev/null +++ b/pkg/store/store_test.go @@ -0,0 +1,392 @@ +package store_test + +import ( + "context" + "database/sql" + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" + "github.com/primevprotocol/mev-oracle/pkg/settler" + "github.com/primevprotocol/mev-oracle/pkg/store" + "github.com/primevprotocol/mev-oracle/pkg/updater" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +func TestStore(t *testing.T) { + ctx := context.Background() + + // Define the PostgreSQL container request + req := testcontainers.ContainerRequest{ + Image: "postgres:latest", + ExposedPorts: []string{"5432/tcp"}, + Env: map[string]string{ + "POSTGRES_DB": "testdb", + "POSTGRES_USER": "user", + "POSTGRES_PASSWORD": "password", + }, + WaitingFor: wait.ForListeningPort("5432/tcp"), + } + + // Start the PostgreSQL container + postgresContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatalf("Failed to start PostgreSQL container: %s", err) + } + defer postgresContainer.Terminate(ctx) + + // Retrieve the container's mapped port + mappedPort, err := postgresContainer.MappedPort(ctx, "5432") + if err != nil { + t.Fatalf("Failed to get mapped port: %s", err) + } + // Construct the database connection string + connStr := fmt.Sprintf("postgresql://user:password@localhost:%s/testdb?sslmode=disable", mappedPort.Port()) + + // Connect to the database + db, err := sql.Open("postgres", connStr) + if err != nil { + t.Fatalf("Failed to connect to PostgreSQL container: %s", err) + } + defer db.Close() + + err = db.Ping() + if err != nil { + t.Fatalf("Failed to ping PostgreSQL container: %s", err) + } + + winners := []updater.BlockWinner{ + { + BlockNumber: 1, + Winner: common.HexToAddress("0x01").String(), + }, + { + BlockNumber: 2, + Winner: common.HexToAddress("0x02").String(), + }, + } + + settlements := []settler.Settlement{ + { + CommitmentIdx: []byte{1}, + TxHash: common.HexToHash("0x01").String(), + BlockNum: 1, + Amount: 2000000, + Builder: winners[0].Winner, + Type: settler.SettlementTypeReward, + }, + { + CommitmentIdx: []byte{2}, + TxHash: common.HexToHash("0x02").String(), + BlockNum: 1, + Amount: 1000000, + Builder: winners[0].Winner, + Type: settler.SettlementTypeSlash, + }, + { + CommitmentIdx: []byte{3}, + TxHash: common.HexToHash("0x03").String(), + BlockNum: 1, + Amount: 1000000, + Builder: winners[1].Winner, + Type: settler.SettlementTypeReturn, + }, + { + CommitmentIdx: []byte{4}, + TxHash: common.HexToHash("0x04").String(), + BlockNum: 2, + Amount: 2000000, + Builder: winners[1].Winner, + Type: settler.SettlementTypeReward, + }, + { + CommitmentIdx: []byte{5}, + TxHash: common.HexToHash("0x05").String(), + BlockNum: 2, + Amount: 1000000, + Builder: winners[1].Winner, + Type: settler.SettlementTypeSlash, + }, + { + CommitmentIdx: []byte{6}, + TxHash: common.HexToHash("0x06").String(), + BlockNum: 2, + Amount: 1000000, + Builder: winners[0].Winner, + Type: settler.SettlementTypeReturn, + }, + } + + t.Run("NewStore", func(t *testing.T) { + // Create the store and tables + _, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + }) + + t.Run("RegisterWinner", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + for _, winner := range winners { + err = st.RegisterWinner(context.Background(), winner.BlockNumber, winner.Winner) + if err != nil { + t.Fatalf("Failed to register winner: %s", err) + } + } + }) + + t.Run("SubscribeWinners", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + ctx, cancel := context.WithCancel(context.Background()) + + // Subscribe to winners + winnerChan := st.SubscribeWinners(ctx) + if err != nil { + t.Fatalf("Failed to subscribe to winners: %s", err) + } + + for i := 0; i < 2; i++ { + winner := <-winnerChan + if winner.BlockNumber != winners[i].BlockNumber { + t.Fatalf("Expected block number %d, got %d", winners[i].BlockNumber, winner.BlockNumber) + } + if winner.Winner != winners[i].Winner { + t.Fatalf("Expected builder address %s, got %s", winners[i].Winner, winner.Winner) + } + } + + cancel() + + winner, ok := <-winnerChan + if ok { + t.Fatalf("Expected channel to be closed, got %v", winner) + } + }) + + t.Run("UpdateComplete", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + // Update the winner as processed + err = st.UpdateComplete(context.Background(), winners[0].BlockNumber) + if err != nil { + t.Fatalf("Failed to update winner: %s", err) + } + + ctx, cancel := context.WithCancel(context.Background()) + + winnerChan := st.SubscribeWinners(ctx) + if err != nil { + t.Fatalf("Failed to subscribe to winners: %s", err) + } + + winner := <-winnerChan + if winner.BlockNumber != winners[1].BlockNumber { + t.Fatalf("Expected block number %d, got %d", winners[1].BlockNumber, winner.BlockNumber) + } + if winner.Winner != winners[1].Winner { + t.Fatalf("Expected builder address %s, got %s", winners[1].Winner, winner.Winner) + } + + cancel() + + winner, ok := <-winnerChan + if ok { + t.Fatalf("Expected channel to be closed, got %v", winner) + } + }) + + t.Run("AddSettlement", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + for _, settlement := range settlements { + err = st.AddSettlement( + context.Background(), + settlement.CommitmentIdx, + settlement.TxHash, + settlement.BlockNum, + settlement.Amount, + settlement.Builder, + settlement.Type, + ) + if err != nil { + t.Fatalf("Failed to add settlement: %s", err) + } + } + }) + + t.Run("SubscribeSettlements", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + ctx, cancel := context.WithCancel(context.Background()) + + settlementChan := st.SubscribeSettlements(ctx) + if err != nil { + t.Fatalf("Failed to subscribe to settlements: %s", err) + } + + for i := 0; i < 6; i++ { + settlement := <-settlementChan + if diff := cmp.Diff(settlement, settlements[i]); diff != "" { + t.Fatalf("Unexpected settlement: (-want +have):\n%s", diff) + } + } + + cancel() + + settlement, ok := <-settlementChan + if ok { + t.Fatalf("Expected channel to be closed, got %v", settlement) + } + }) + + t.Run("SettlementInitiated", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + indexes := make([][]byte, 2) + for i := 0; i < 3; i++ { + indexes[0] = settlements[2*i].CommitmentIdx + indexes[1] = settlements[2*i+1].CommitmentIdx + + err = st.SettlementInitiated( + context.Background(), + indexes, + common.HexToHash(fmt.Sprintf("0x%02d", i)), + uint64(i+1), + ) + if err != nil { + t.Fatalf("Failed to initiate settlement: %s", err) + } + } + }) + + t.Run("LastNonce and PendingTxnCount", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + lastNonce, err := st.LastNonce() + if err != nil { + t.Fatalf("Failed to get last nonce: %s", err) + } + if lastNonce != 3 { + t.Fatalf("Expected last nonce 3, got %d", lastNonce) + } + + pendingTxnCount, err := st.PendingTxnCount() + if err != nil { + t.Fatalf("Failed to get pending txn count: %s", err) + } + if pendingTxnCount != 3 { + t.Fatalf("Expected pending txn count 3, got %d", pendingTxnCount) + } + }) + + t.Run("MarkSettlementComplete", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + count, err := st.MarkSettlementComplete(context.Background(), 4) + if err != nil { + t.Fatalf("Failed to mark settlement complete: %s", err) + } + if count != 6 { + t.Fatalf("Expected count 6, got %d", count) + } + + pendingTxnCount, err := st.PendingTxnCount() + if err != nil { + t.Fatalf("Failed to get pending txn count: %s", err) + } + if pendingTxnCount != 0 { + t.Fatalf("Expected pending txn count 0, got %d", pendingTxnCount) + } + }) + + t.Run("stats", func(t *testing.T) { + st, err := store.NewStore(db) + if err != nil { + t.Fatalf("Failed to create store: %s", err) + } + + stats, err := st.CommitmentStats() + if err != nil { + t.Fatalf("Failed to get stats: %s", err) + } + if stats.TotalCount != 6 { + t.Fatalf("Expected total count 6, got %d", stats.TotalCount) + } + if stats.RewardCount != 2 { + t.Fatalf("Expected reward count 2, got %d", stats.RewardCount) + } + if stats.SlashCount != 2 { + t.Fatalf("Expected slash count 2, got %d", stats.SlashCount) + } + if stats.SettlementsCompletedCount != 6 { + t.Fatalf("Expected settlements completed count 6, got %d", stats.SettlementsCompletedCount) + } + + blockStats, err := st.ProcessedBlocks(2, 0) + if err != nil { + t.Fatalf("Failed to get processed blocks: %s", err) + } + if len(blockStats) != 1 { + t.Fatalf("Expected 1 block stats, got %d", len(blockStats)) + } + block := blockStats[0] + if block.BlockNumber != winners[0].BlockNumber { + t.Fatalf("Expected block number %d, got %d", winners[0].BlockNumber, block.BlockNumber) + } + if block.Builder != winners[0].Winner { + t.Fatalf("Expected builder address %s, got %s", winners[0].Winner, block.Builder) + } + if block.NoOfCommitments != 3 { + t.Fatalf("Expected no of commitments 3, got %d", block.NoOfCommitments) + } + if block.TotalAmount != 4000000 { + t.Fatalf("Expected total amount 5000000, got %d", block.TotalAmount) + } + if block.NoOfRewards != 1 { + t.Fatalf("Expected no of rewards 1, got %d", block.NoOfRewards) + } + if block.TotalRewards != 2000000 { + t.Fatalf("Expected total rewards 2000000, got %d", block.TotalRewards) + } + if block.NoOfSlashes != 1 { + t.Fatalf("Expected no of slashes 2, got %d", block.NoOfSlashes) + } + if block.TotalSlashes != 1000000 { + t.Fatalf("Expected total slashes 2000000, got %d", block.TotalSlashes) + } + if block.NoOfSettlements != 3 { + t.Fatalf("Expected no of settlements 3, got %d", block.NoOfSettlements) + } + }) +} diff --git a/pkg/updater/metrics.go b/pkg/updater/metrics.go index b6d034f..4ad138d 100644 --- a/pkg/updater/metrics.go +++ b/pkg/updater/metrics.go @@ -9,7 +9,8 @@ const ( type metrics struct { UpdaterTriggerCount prometheus.Counter - CommimentsCount prometheus.Counter + CommitmentsCount prometheus.Counter + RewardsCount prometheus.Counter SlashesCount prometheus.Counter BlockCommitmentsCount prometheus.Counter } @@ -24,14 +25,22 @@ func newMetrics() *metrics { Help: "Number of times the updater was triggered", }, ) - m.CommimentsCount = prometheus.NewCounter( + m.CommitmentsCount = prometheus.NewCounter( prometheus.CounterOpts{ Namespace: defaultNamespace, Subsystem: subsystem, - Name: "commiments_count", + Name: "commitments_count", Help: "Number of commitments processed", }, ) + m.RewardsCount = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: defaultNamespace, + Subsystem: subsystem, + Name: "rewards_count", + Help: "Number of rewards", + }, + ) m.SlashesCount = prometheus.NewCounter( prometheus.CounterOpts{ Namespace: defaultNamespace, @@ -54,7 +63,8 @@ func newMetrics() *metrics { func (m *metrics) Collectors() []prometheus.Collector { return []prometheus.Collector{ m.UpdaterTriggerCount, - m.CommimentsCount, + m.CommitmentsCount, + m.RewardsCount, m.SlashesCount, m.BlockCommitmentsCount, } diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index c547907..28ca316 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" preconf "github.com/primevprotocol/contracts-abi/clients/PreConfCommitmentStore" + "github.com/primevprotocol/mev-oracle/pkg/settler" "github.com/prometheus/client_golang/prometheus" "github.com/rs/zerolog/log" ) @@ -28,8 +29,9 @@ type WinnerRegister interface { commitmentIdx []byte, txHash string, blockNum int64, + amount uint64, builder string, - isSlash bool, + settlementType settler.SettlementType, ) error } @@ -137,39 +139,48 @@ func (u *Updater) Start(ctx context.Context) <-chan struct{} { Int64("blockNumber", winner.BlockNumber). Msg("commitment indexes") - count, slashes := 0, 0 + total, rewards, slashes := 0, 0, 0 for _, index := range commitmentIndexes { commitment, err := u.preconfClient.GetCommitment(index) if err != nil { return fmt.Errorf("failed to get commitment: %w", err) } + settlementType := settler.SettlementTypeReturn + if commitment.Commiter.Cmp(builderAddr) == 0 { commitmentTxnHashes := strings.Split(commitment.TxnHash, ",") - ok := true + settlementType = settler.SettlementTypeReward // Ensure Bundle is atomic and present in the block - for i := 0; i < len(commitmentTxnHashes) && ok; i++ { - if newPos, found := txnsInBlock[commitmentTxnHashes[i]]; !found || newPos != txnsInBlock[commitmentTxnHashes[0]]+i { - ok = false + for i := 0; i < len(commitmentTxnHashes); i++ { + posInBlock, found := txnsInBlock[commitmentTxnHashes[i]] + if !found || posInBlock != txnsInBlock[commitmentTxnHashes[0]]+i { + settlementType = settler.SettlementTypeSlash break } } - err = u.winnerRegister.AddSettlement( - ctx, - index[:], - commitment.TxnHash, - winner.BlockNumber, - winner.Winner, - !ok, - ) - if err != nil { - return fmt.Errorf("failed to add settlement: %w", err) - } - count++ - if !ok { - slashes++ - } + } + + err = u.winnerRegister.AddSettlement( + ctx, + index[:], + commitment.TxnHash, + winner.BlockNumber, + commitment.Bid, + winner.Winner, + settlementType, + ) + if err != nil { + return fmt.Errorf("failed to add settlement: %w", err) + } + + total++ + switch settlementType { + case settler.SettlementTypeSlash: + slashes++ + case settler.SettlementTypeReward: + rewards++ } } @@ -178,12 +189,15 @@ func (u *Updater) Start(ctx context.Context) <-chan struct{} { return fmt.Errorf("failed to update completion of block updates: %w", err) } - u.metrics.CommimentsCount.Add(float64(len(commitmentIndexes))) - u.metrics.BlockCommitmentsCount.Inc() + u.metrics.CommitmentsCount.Add(float64(total)) + u.metrics.RewardsCount.Add(float64(rewards)) u.metrics.SlashesCount.Add(float64(slashes)) + u.metrics.BlockCommitmentsCount.Inc() log.Info(). - Int("count", count). + Int("total", total). + Int("rewards", rewards). + Int("slashes", slashes). Int64("blockNumber", winner.BlockNumber). Str("winner", winner.Winner). Msg("added settlements") diff --git a/pkg/updater/updater_test.go b/pkg/updater/updater_test.go index 263eca3..ba60290 100644 --- a/pkg/updater/updater_test.go +++ b/pkg/updater/updater_test.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" preconf "github.com/primevprotocol/contracts-abi/clients/PreConfCommitmentStore" + "github.com/primevprotocol/mev-oracle/pkg/settler" "github.com/primevprotocol/mev-oracle/pkg/updater" "golang.org/x/crypto/sha3" ) @@ -57,6 +58,7 @@ func TestUpdater(t *testing.T) { } builderAddr := common.HexToAddress("0xabcd") + otherBuilderAddr := common.HexToAddress("0xabdc") signer := types.NewLondonSigner(big.NewInt(5)) var txns []*types.Transaction @@ -74,9 +76,16 @@ func TestUpdater(t *testing.T) { for i, txn := range txns { idxBytes := getIdxBytes(int64(i)) - commitments[string(idxBytes[:])] = preconf.PreConfCommitmentStorePreConfCommitment{ - Commiter: builderAddr, - TxnHash: txn.Hash().Hex(), + if i%2 == 0 { + commitments[string(idxBytes[:])] = preconf.PreConfCommitmentStorePreConfCommitment{ + Commiter: builderAddr, + TxnHash: txn.Hash().Hex(), + } + } else { + commitments[string(idxBytes[:])] = preconf.PreConfCommitmentStorePreConfCommitment{ + Commiter: otherBuilderAddr, + TxnHash: txn.Hash().Hex(), + } } } @@ -132,6 +141,7 @@ func TestUpdater(t *testing.T) { } count := 0 + rewards, returns := 0, 0 for { if count == 20 { break @@ -143,12 +153,25 @@ func TestUpdater(t *testing.T) { if settlement.builder != "test" { t.Fatal("wrong builder") } - if settlement.isSlash { + if settlement.settlementType == settler.SettlementTypeSlash { t.Fatal("should not be slash") } + if settlement.settlementType == settler.SettlementTypeReward { + rewards++ + } + if settlement.settlementType == settler.SettlementTypeReturn { + returns++ + } count++ } + if rewards != 15 { + t.Fatal("wrong rewards count") + } + if returns != 5 { + t.Fatal("wrong returns count") + } + select { case <-testWinnerRegister.done: case <-time.After(5 * time.Second): @@ -249,8 +272,8 @@ func TestUpdaterBundlesFailure(t *testing.T) { if settlement.builder != "test" { t.Fatal("wrong builder") } - if !settlement.isSlash { - t.Fatal("should be slash") + if settlement.settlementType != settler.SettlementTypeSlash { + t.Fatalf("should be slash, got %s", settlement.settlementType) } count++ } @@ -270,11 +293,12 @@ func TestUpdaterBundlesFailure(t *testing.T) { } type testSettlement struct { - commitmentIdx []byte - txHash string - blockNum int64 - builder string - isSlash bool + commitmentIdx []byte + txHash string + blockNum int64 + builder string + amount uint64 + settlementType settler.SettlementType } type testWinnerRegister struct { @@ -297,15 +321,17 @@ func (t *testWinnerRegister) AddSettlement( commitmentIdx []byte, txHash string, blockNum int64, + amount uint64, builder string, - isSlash bool, + settlementType settler.SettlementType, ) error { t.settlements <- testSettlement{ - commitmentIdx: commitmentIdx, - txHash: txHash, - blockNum: blockNum, - builder: builder, - isSlash: isSlash, + commitmentIdx: commitmentIdx, + txHash: txHash, + blockNum: blockNum, + amount: amount, + builder: builder, + settlementType: settlementType, } return nil } From 0daa5712cbb1e0fc0159a0f1d758f31b39814b2a Mon Sep 17 00:00:00 2001 From: Alok Date: Sat, 3 Feb 2024 20:45:29 +0530 Subject: [PATCH 2/3] feat: update command to use env or config --- Dockerfile | 1 - Dockerfile.release | 14 --- cmd/main.go | 293 +++++++++++++++++++++++++++++++-------------- config.yaml | 23 ++-- go.mod | 2 + go.sum | 2 + key | 1 - 7 files changed, 219 insertions(+), 117 deletions(-) delete mode 100644 Dockerfile.release delete mode 100644 key diff --git a/Dockerfile b/Dockerfile index bcf872e..f625cc2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,6 @@ RUN CGO_ENABLED=0 GOOS=linux go build -o mev-commit-oracle ./cmd/main.go FROM alpine:latest COPY --from=builder /app/mev-commit-oracle /usr/local/bin/mev-commit-oracle -COPY --from=builder /app/key /key COPY --from=builder /app/config.yaml /config.yaml COPY --from=builder /app/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh diff --git a/Dockerfile.release b/Dockerfile.release deleted file mode 100644 index 20be6b7..0000000 --- a/Dockerfile.release +++ /dev/null @@ -1,14 +0,0 @@ -FROM golang:1.21.1 AS builder - -WORKDIR /app -COPY . . - -RUN CGO_ENABLED=0 GOOS=linux go build -o mev-commit-oracle ./cmd/main.go - -FROM alpine:latest - -COPY --from=builder /app/mev-commit-oracle /usr/local/bin/mev-commit-oracle - -EXPOSE 8080 - -ENTRYPOINT ["mev-commit-oracle", "start"] diff --git a/cmd/main.go b/cmd/main.go index fe2c8c5..364d424 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,6 +1,7 @@ package main import ( + "crypto/ecdsa" "fmt" "os" "path/filepath" @@ -9,37 +10,163 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + contracts "github.com/primevprotocol/contracts-abi/config" "github.com/primevprotocol/mev-oracle/pkg/node" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" - "gopkg.in/yaml.v2" + "github.com/urfave/cli/v2/altsrc" + "golang.org/x/crypto/sha3" ) const ( - defaultHTTPPort = 8080 + defaultHTTPPort = 8080 + defaultConfigDir = "~/.mev-commit-oracle" + defaultKeyFile = "key" ) var ( optionConfig = &cli.StringFlag{ - Name: "config", - Usage: "path to config file", - Required: true, - EnvVars: []string{"MEV_ORACLE_CONFIG"}, + Name: "config", + Usage: "path to config file", + EnvVars: []string{"MEV_ORACLE_CONFIG"}, } + + optionPrivKeyFile = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "priv-key-file", + Usage: "path to private key file", + EnvVars: []string{"MEV_ORACLE_PRIV_KEY_FILE"}, + Value: filepath.Join(defaultConfigDir, defaultKeyFile), + }) + + optionHTTPPort = altsrc.NewIntFlag(&cli.IntFlag{ + Name: "http-port", + Usage: "port to listen on for HTTP requests", + EnvVars: []string{"MEV_ORACLE_HTTP_PORT"}, + Value: defaultHTTPPort, + Action: func(c *cli.Context, p int) error { + if p < 0 || p > 65535 { + return fmt.Errorf("invalid port number: %d", p) + } + return nil + }, + }) + + optionLogLevel = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "log-level", + Usage: "log level", + EnvVars: []string{"MEV_ORACLE_LOG_LEVEL"}, + Value: "info", + Action: func(c *cli.Context, l string) error { + _, err := zerolog.ParseLevel(l) + return err + }, + }) + + optionL1RPCUrl = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "l1-rpc-url", + Usage: "URL for L1 RPC", + EnvVars: []string{"MEV_ORACLE_L1_RPC_URL"}, + Required: true, + }) + + optionSettlementRPCUrl = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "settlement-rpc-url", + Usage: "URL for settlement RPC", + EnvVars: []string{"MEV_ORACLE_SETTLEMENT_RPC_URL"}, + Value: "http://localhost:8545", + }) + + optionOracleContractAddr = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "oracle-contract-addr", + Usage: "address of the oracle contract", + EnvVars: []string{"MEV_ORACLE_ORACLE_CONTRACT_ADDR"}, + Value: contracts.TestnetContracts.Oracle, + }) + + optionPreconfContractAddr = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "preconf-contract-addr", + Usage: "address of the preconf contract", + EnvVars: []string{"MEV_ORACLE_PRECONF_CONTRACT_ADDR"}, + Value: contracts.TestnetContracts.PreconfCommitmentStore, + }) + + optionPgHost = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "pg-host", + Usage: "PostgreSQL host", + EnvVars: []string{"MEV_ORACLE_PG_HOST"}, + Value: "localhost", + }) + + optionPgPort = altsrc.NewIntFlag(&cli.IntFlag{ + Name: "pg-port", + Usage: "PostgreSQL port", + EnvVars: []string{"MEV_ORACLE_PG_PORT"}, + Value: 5432, + }) + + optionPgUser = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "pg-user", + Usage: "PostgreSQL user", + EnvVars: []string{"MEV_ORACLE_PG_USER"}, + Value: "postgres", + }) + + optionPgPassword = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "pg-password", + Usage: "PostgreSQL password", + EnvVars: []string{"MEV_ORACLE_PG_PASSWORD"}, + Value: "postgres", + }) + + optionPgDbname = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "pg-dbname", + Usage: "PostgreSQL database name", + EnvVars: []string{"MEV_ORACLE_PG_DBNAME"}, + Value: "mev_oracle", + }) + + optionLaggerdMode = altsrc.NewIntFlag(&cli.IntFlag{ + Name: "laggerd-mode", + Usage: "No of blocks to lag behind for L1 chain", + EnvVars: []string{"MEV_ORACLE_LAGGERD_MODE"}, + Value: 0, + }) + + optionOverrideWinners = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{ + Name: "override-winners", + Usage: "Override winners for testing", + EnvVars: []string{"MEV_ORACLE_OVERRIDE_WINNERS"}, + }) ) func main() { + flags := []cli.Flag{ + optionConfig, + optionPrivKeyFile, + optionHTTPPort, + optionLogLevel, + optionL1RPCUrl, + optionSettlementRPCUrl, + optionOracleContractAddr, + optionPreconfContractAddr, + optionPgHost, + optionPgPort, + optionPgUser, + optionPgPassword, + optionPgDbname, + optionLaggerdMode, + optionOverrideWinners, + } app := &cli.App{ Name: "mev-oracle", Usage: "Entry point for mev-oracle", Commands: []*cli.Command{ { - Name: "start", - Usage: "Start the mev-oracle node", - Flags: []cli.Flag{ - optionConfig, - }, + Name: "start", + Usage: "Start the mev-oracle node", + Flags: flags, + Before: altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc(optionConfig.Name)), Action: func(c *cli.Context) error { return start(c) }, @@ -51,117 +178,107 @@ func main() { } } -type config struct { - PrivKeyFile string `yaml:"priv_key_file" json:"priv_key_file"` - HTTPPort int `yaml:"http_port" json:"http_port"` - LogLevel string `yaml:"log_level" json:"log_level"` - L1RPCUrl string `yaml:"l1_rpc_url" json:"l1_rpc_url"` - SettlementRPCUrl string `yaml:"settlement_rpc_url" json:"settlement_rpc_url"` - OracleContractAddr string `yaml:"oracle_contract_addr" json:"oracle_contract_addr"` - PreconfContractAddr string `yaml:"preconf_contract_addr" json:"preconf_contract_addr"` - PgHost string `yaml:"pg_host" json:"pg_host"` - PgPort int `yaml:"pg_port" json:"pg_port"` - PgUser string `yaml:"pg_user" json:"pg_user"` - PgPassword string `yaml:"pg_password" json:"pg_password"` - PgDbname string `yaml:"pg_dbname" json:"pg_dbname"` - LaggerdMode int `yaml:"laggerd_mode" json:"laggerd_mode"` - OverrideWinners []string `yaml:"override_winners" json:"override_winners"` -} - -func checkConfig(cfg *config) error { - if cfg.PrivKeyFile == "" { - return fmt.Errorf("priv_key_file is required") +func createKeyIfNotExists(c *cli.Context, path string) error { + // check if key already exists + if _, err := os.Stat(path); err == nil { + fmt.Fprintf(c.App.Writer, "Using existing private key: %s\n", path) + return nil } - if cfg.HTTPPort == 0 { - cfg.HTTPPort = defaultHTTPPort - } + fmt.Fprintf(c.App.Writer, "Creating new private key: %s\n", path) - if cfg.LogLevel == "" { - cfg.LogLevel = "info" + // check if parent directory exists + if _, err := os.Stat(filepath.Dir(path)); os.IsNotExist(err) { + // create parent directory + if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { + return err + } } - if cfg.L1RPCUrl == "" { - return fmt.Errorf("l1_rpc_url is required") + privKey, err := crypto.GenerateKey() + if err != nil { + return err } - if cfg.SettlementRPCUrl == "" { - return fmt.Errorf("settlement_rpc_url is required") + f, err := os.Create(path) + if err != nil { + return err } - if cfg.OracleContractAddr == "" { - return fmt.Errorf("oracle_contract_addr is required") - } + defer f.Close() - if cfg.PreconfContractAddr == "" { - return fmt.Errorf("preconf_contract_addr is required") + if err := crypto.SaveECDSA(path, privKey); err != nil { + return err } - if cfg.PgHost == "" || cfg.PgPort == 0 || cfg.PgUser == "" || cfg.PgPassword == "" || cfg.PgDbname == "" { - return fmt.Errorf("pg_host, pg_port, pg_user, pg_password, pg_dbname are required") - } + wallet := getEthAddressFromPubKey(&privKey.PublicKey) + fmt.Fprintf(c.App.Writer, "Private key saved to file: %s\n", path) + fmt.Fprintf(c.App.Writer, "Wallet address: %s\n", wallet.Hex()) return nil } -func start(c *cli.Context) error { - configFile := c.String(optionConfig.Name) - fmt.Fprintf(c.App.Writer, "starting mev-oracle with config file: %s\n", configFile) - - var cfg config - buf, err := os.ReadFile(configFile) - if err != nil { - return fmt.Errorf("failed to read config file at '%s': %w", configFile, err) +func resolveFilePath(path string) (string, error) { + if path == "" { + return "", fmt.Errorf("path is empty") } - if err := yaml.Unmarshal(buf, &cfg); err != nil { - return fmt.Errorf("failed to unmarshal config file at '%s': %w", configFile, err) - } + if strings.HasPrefix(path, "~") { + home, err := os.UserHomeDir() + if err != nil { + return "", err + } - if err := checkConfig(&cfg); err != nil { - return fmt.Errorf("invalid config file at '%s': %w", configFile, err) + return filepath.Join(home, path[1:]), nil } - lvl, err := zerolog.ParseLevel(cfg.LogLevel) + return path, nil +} + +func getEthAddressFromPubKey(key *ecdsa.PublicKey) common.Address { + pbBytes := crypto.FromECDSAPub(key) + hash := sha3.NewLegacyKeccak256() + hash.Write(pbBytes[1:]) + address := hash.Sum(nil)[12:] + + return common.BytesToAddress(address) +} + +func start(c *cli.Context) error { + privKeyFile, err := resolveFilePath(c.String(optionPrivKeyFile.Name)) if err != nil { - return fmt.Errorf("failed to parse log level '%s': %w", cfg.LogLevel, err) + return fmt.Errorf("failed to get private key file path: %w", err) + } + + if err := createKeyIfNotExists(c, privKeyFile); err != nil { + return fmt.Errorf("failed to create private key: %w", err) } + lvl, _ := zerolog.ParseLevel(c.String(optionLogLevel.Name)) + zerolog.SetGlobalLevel(lvl) zerolog.TimeFieldFormat = zerolog.TimeFormatUnix log.Logger = log.Output(os.Stdout).With().Caller().Logger() - privKeyFile := cfg.PrivKeyFile - if strings.HasPrefix(privKeyFile, "~/") { - homeDir, err := os.UserHomeDir() - if err != nil { - return fmt.Errorf("failed to get user home directory: %w", err) - } - - privKeyFile = filepath.Join(homeDir, privKeyFile[2:]) - } - privKey, err := crypto.LoadECDSA(privKeyFile) if err != nil { - return fmt.Errorf("failed to load private key from file '%s': %w", cfg.PrivKeyFile, err) + return fmt.Errorf("failed to load private key from file '%s': %w", privKeyFile, err) } - common.HexToAddress(cfg.OracleContractAddr) - nd, err := node.NewNode(&node.Options{ PrivateKey: privKey, - HTTPPort: cfg.HTTPPort, - L1RPCUrl: cfg.L1RPCUrl, - SettlementRPCUrl: cfg.SettlementRPCUrl, - OracleContractAddr: common.HexToAddress(cfg.OracleContractAddr), - PreconfContractAddr: common.HexToAddress(cfg.PreconfContractAddr), - PgHost: cfg.PgHost, - PgPort: cfg.PgPort, - PgUser: cfg.PgUser, - PgPassword: cfg.PgPassword, - PgDbname: cfg.PgDbname, - LaggerdMode: cfg.LaggerdMode, - OverrideWinners: cfg.OverrideWinners, + HTTPPort: c.Int(optionHTTPPort.Name), + L1RPCUrl: c.String(optionL1RPCUrl.Name), + SettlementRPCUrl: c.String(optionSettlementRPCUrl.Name), + OracleContractAddr: common.HexToAddress(c.String(optionOracleContractAddr.Name)), + PreconfContractAddr: common.HexToAddress(c.String(optionPreconfContractAddr.Name)), + PgHost: c.String(optionPgHost.Name), + PgPort: c.Int(optionPgPort.Name), + PgUser: c.String(optionPgUser.Name), + PgPassword: c.String(optionPgPassword.Name), + PgDbname: c.String(optionPgDbname.Name), + LaggerdMode: c.Int(optionLaggerdMode.Name), + OverrideWinners: c.StringSlice(optionOverrideWinners.Name), }) if err != nil { return fmt.Errorf("failed starting node: %w", err) diff --git a/config.yaml b/config.yaml index 33508a4..ac19982 100644 --- a/config.yaml +++ b/config.yaml @@ -1,16 +1,13 @@ -priv_key_file: /key -log_level: debug -l1_rpc_url: -settlement_rpc_url: http://sl-bootnode:8545 -oracle_contract_addr: 0x943685b6999626D2323526ce3fb6EF1786Ee8Ee3 -preconf_contract_addr: 0x451656c1E7eDf82397EBE04f38819c9970AA3658 -pg_host: oracle-db -pg_port: 5432 -pg_user: oracle_user -pg_password: oracle_pass -pg_dbname: oracle_db -laggerd_mode: 10 -override_winners: +log-level: debug +l1-rpc-url: +settlement-rpc-url: http://sl-bootnode:8545 +pg-host: oracle-db +pg-port: 5432 +pg-user: oracle_user +pg-password: oracle_pass +pg-dbname: oracle_db +laggerd-mode: 10 +override-winners: - 0x48ddC642514370bdaFAd81C91e23759B0302C915 - 0x972eb4Fc3c457da4C957306bE7Fa1976BB8F39A6 - 0xA1e8FDB3bb6A0DB7aA5Db49a3512B01671686DCB diff --git a/go.mod b/go.mod index 58dc11b..8293102 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( require ( dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/BurntSushi/toml v1.3.2 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect @@ -93,5 +94,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/grpc v1.58.3 // indirect google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 6397e67..bf0afc1 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= diff --git a/key b/key deleted file mode 100644 index df206ad..0000000 --- a/key +++ /dev/null @@ -1 +0,0 @@ -ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 From 6dee5bbb411c7a1f211586c85734e693d144ca0e Mon Sep 17 00:00:00 2001 From: Alok Date: Sat, 3 Feb 2024 20:58:08 +0530 Subject: [PATCH 3/3] fix: lint --- pkg/settler/settler.go | 2 -- pkg/store/store_test.go | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/settler/settler.go b/pkg/settler/settler.go index 6705729..a510637 100644 --- a/pkg/settler/settler.go +++ b/pkg/settler/settler.go @@ -282,8 +282,6 @@ func (s *Settler) Start(ctx context.Context) <-chan struct{} { return err } - commitmentIndexes = commitmentIndexes[:0] - s.metrics.LastUsedNonce.Set(float64(commitmentPostingTxn.Nonce())) s.metrics.SettlementsPostedCount.Inc() s.metrics.CurrentSettlementL1Block.Set(float64(settlement.BlockNum)) diff --git a/pkg/store/store_test.go b/pkg/store/store_test.go index 3bb1ad6..b3a2d73 100644 --- a/pkg/store/store_test.go +++ b/pkg/store/store_test.go @@ -38,7 +38,12 @@ func TestStore(t *testing.T) { if err != nil { t.Fatalf("Failed to start PostgreSQL container: %s", err) } - defer postgresContainer.Terminate(ctx) + defer func() { + err := postgresContainer.Terminate(ctx) + if err != nil { + t.Errorf("Failed to terminate PostgreSQL container: %s", err) + } + }() // Retrieve the container's mapped port mappedPort, err := postgresContainer.MappedPort(ctx, "5432")