From 3236f799e501be227da6e42e7b41a4928750115c Mon Sep 17 00:00:00 2001 From: authcall Date: Thu, 27 Jul 2023 10:52:10 -0700 Subject: [PATCH 1/9] feat: protocol-parser in go (#1116) Co-authored-by: alvarius --- .changeset/big-goats-prove.md | 5 + packages/services/go.mod | 36 +- packages/services/go.sum | 107 ++--- packages/services/package.json | 3 +- .../pkg/protocol-parser/abiTypesToSchema.go | 21 + .../protocol-parser/abiTypesToSchema_test.go | 64 +++ .../services/pkg/protocol-parser/common.go | 13 + .../pkg/protocol-parser/decodeDynamicField.go | 137 ++++++ .../decodeDynamicField_test.go | 408 ++++++++++++++++++ .../pkg/protocol-parser/decodeField.go | 11 + .../pkg/protocol-parser/decodeKeyTuple.go | 43 ++ .../protocol-parser/decodeKeyTuple_test.go | 81 ++++ .../pkg/protocol-parser/decodeRecord.go | 42 ++ .../pkg/protocol-parser/decodeRecord_test.go | 48 +++ .../pkg/protocol-parser/decodeStaticField.go | 133 ++++++ .../protocol-parser/decodeStaticField_test.go | 347 +++++++++++++++ .../pkg/protocol-parser/encodeField.go | 28 ++ .../pkg/protocol-parser/encodeKeyTuple.go | 18 + .../protocol-parser/encodeKeyTuple_test.go | 66 +++ .../pkg/protocol-parser/encodeRecord.go | 58 +++ .../pkg/protocol-parser/encodeRecord_test.go | 56 +++ .../services/pkg/protocol-parser/errors.go | 12 + .../pkg/protocol-parser/hexToPackedCounter.go | 35 ++ .../hexToPackedCounter_test.go | 53 +++ .../pkg/protocol-parser/hexToSchema.go | 39 ++ .../pkg/protocol-parser/hexToSchema_test.go | 83 ++++ .../pkg/protocol-parser/hexToTableSchema.go | 11 + .../protocol-parser/schemaIndexToAbiType.go | 10 + .../schemaIndexToAbiType_test.go | 39 ++ .../pkg/protocol-parser/schemaToHex.go | 27 ++ .../pkg/protocol-parser/schemaToHex_test.go | 51 +++ .../pkg/protocol-parser/staticDataLength.go | 11 + .../services/pkg/protocol-parser/utils.go | 39 ++ .../pkg/protocol-parser/utils_test.go | 101 +++++ .../services/pkg/schema-type/arrayAbiTypes.go | 9 + .../pkg/schema-type/schematype_string.go | 220 ++++++++++ .../pkg/schema-type/staticAbiTypes.go | 208 +++++++++ packages/services/pkg/schema-type/types.go | 238 ++++++++++ 38 files changed, 2845 insertions(+), 66 deletions(-) create mode 100644 .changeset/big-goats-prove.md create mode 100644 packages/services/pkg/protocol-parser/abiTypesToSchema.go create mode 100644 packages/services/pkg/protocol-parser/abiTypesToSchema_test.go create mode 100644 packages/services/pkg/protocol-parser/common.go create mode 100644 packages/services/pkg/protocol-parser/decodeDynamicField.go create mode 100644 packages/services/pkg/protocol-parser/decodeDynamicField_test.go create mode 100644 packages/services/pkg/protocol-parser/decodeField.go create mode 100644 packages/services/pkg/protocol-parser/decodeKeyTuple.go create mode 100644 packages/services/pkg/protocol-parser/decodeKeyTuple_test.go create mode 100644 packages/services/pkg/protocol-parser/decodeRecord.go create mode 100644 packages/services/pkg/protocol-parser/decodeRecord_test.go create mode 100644 packages/services/pkg/protocol-parser/decodeStaticField.go create mode 100644 packages/services/pkg/protocol-parser/decodeStaticField_test.go create mode 100644 packages/services/pkg/protocol-parser/encodeField.go create mode 100644 packages/services/pkg/protocol-parser/encodeKeyTuple.go create mode 100644 packages/services/pkg/protocol-parser/encodeKeyTuple_test.go create mode 100644 packages/services/pkg/protocol-parser/encodeRecord.go create mode 100644 packages/services/pkg/protocol-parser/encodeRecord_test.go create mode 100644 packages/services/pkg/protocol-parser/errors.go create mode 100644 packages/services/pkg/protocol-parser/hexToPackedCounter.go create mode 100644 packages/services/pkg/protocol-parser/hexToPackedCounter_test.go create mode 100644 packages/services/pkg/protocol-parser/hexToSchema.go create mode 100644 packages/services/pkg/protocol-parser/hexToSchema_test.go create mode 100644 packages/services/pkg/protocol-parser/hexToTableSchema.go create mode 100644 packages/services/pkg/protocol-parser/schemaIndexToAbiType.go create mode 100644 packages/services/pkg/protocol-parser/schemaIndexToAbiType_test.go create mode 100644 packages/services/pkg/protocol-parser/schemaToHex.go create mode 100644 packages/services/pkg/protocol-parser/schemaToHex_test.go create mode 100644 packages/services/pkg/protocol-parser/staticDataLength.go create mode 100644 packages/services/pkg/protocol-parser/utils.go create mode 100644 packages/services/pkg/protocol-parser/utils_test.go create mode 100644 packages/services/pkg/schema-type/arrayAbiTypes.go create mode 100644 packages/services/pkg/schema-type/schematype_string.go create mode 100644 packages/services/pkg/schema-type/staticAbiTypes.go create mode 100644 packages/services/pkg/schema-type/types.go diff --git a/.changeset/big-goats-prove.md b/.changeset/big-goats-prove.md new file mode 100644 index 0000000000..049248db7b --- /dev/null +++ b/.changeset/big-goats-prove.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/services": patch +--- + +protocol-parser in Go diff --git a/packages/services/go.mod b/packages/services/go.mod index 6cec1e8f10..61ead04818 100644 --- a/packages/services/go.mod +++ b/packages/services/go.mod @@ -1,13 +1,15 @@ module latticexyz/mud/packages/services -go 1.18 +go 1.20 replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v1.101105.1 require ( + github.com/andriidski/abiencode-go v0.0.0-20230709002942-ad6b06528e3e github.com/avast/retry-go v3.0.0+incompatible github.com/dghubble/go-twitter v0.0.0-20220816163853-8a0df96f1e6d - github.com/ethereum/go-ethereum v1.10.26 + github.com/ethereum/go-ethereum v1.12.0 + github.com/golodash/godash v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/improbable-eng/grpc-web v0.15.0 github.com/jackc/pglogrepl v0.0.0-20221125161640-1e972958ba03 @@ -15,12 +17,11 @@ require ( github.com/jmoiron/sqlx v1.3.5 github.com/keith-turner/ecoji v1.0.0 github.com/lib/pq v1.10.2 - github.com/ompluscator/dynamic-struct v1.4.0 - github.com/prometheus/client_golang v1.11.1 + github.com/prometheus/client_golang v1.14.0 github.com/umbracle/ethgo v0.1.3 go.uber.org/zap v1.22.0 - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d - golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba + golang.org/x/oauth2 v0.3.0 + golang.org/x/time v0.0.0-20220922220347-f3bd1da661af google.golang.org/grpc v1.48.0 google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v3 v3.0.1 @@ -33,30 +34,31 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/deckarep/golang-set v1.8.0 // indirect + github.com/cespare/xxhash/v2 v2.2.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/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dghubble/sling v1.4.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-stack/stack v1.8.0 // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.15.9 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/klauspost/compress v1.15.15 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect - github.com/rjeczalik/notify v0.9.1 // 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/rs/cors v1.7.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect @@ -69,7 +71,7 @@ require ( golang.org/x/net v0.9.0 // indirect golang.org/x/sys v0.7.0 // indirect golang.org/x/text v0.9.0 // indirect - google.golang.org/appengine v1.6.5 // indirect + google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect nhooyr.io/websocket v1.8.6 // indirect diff --git a/packages/services/go.sum b/packages/services/go.sum index 1a91c205b4..dea7fffc43 100644 --- a/packages/services/go.sum +++ b/packages/services/go.sum @@ -4,6 +4,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.4.13 h1:Hmi80lzZuI/CaYmlJp/b+FjZdRZhKu9c2mDVqKlLWVs= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= @@ -19,6 +20,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/andriidski/abiencode-go v0.0.0-20230709002942-ad6b06528e3e h1:bpxR7K2TE9OFy1soiYBNppzw0YsiVzm2dT0oQ59Xgkc= +github.com/andriidski/abiencode-go v0.0.0-20230709002942-ad6b06528e3e/go.mod h1:PdE3osjL/L7ol74PwcP736uCVrJwRApb63GGbxfeNAo= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -49,8 +52,9 @@ github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8 github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= 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/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -60,6 +64,10 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b h1:pik3LX++5O3UiNWv45wfP/WT81l7ukBJzd3uUiifbSU= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -72,8 +80,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= -github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= @@ -91,7 +99,6 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -100,14 +107,17 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= -github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= +github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= 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= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -117,7 +127,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= @@ -133,18 +142,21 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +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 h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -168,7 +180,9 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golodash/godash v1.3.0 h1:/2KCxYrpzFiSakuDFTcKOjIAXO7Y00ITGVoACpaPbhM= +github.com/golodash/godash v1.3.0/go.mod h1:oKwxn9UMkI6aa9OiR56sRw7Z5SokrfZSybLjSQ6OB5s= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -177,10 +191,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.2/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.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -189,8 +202,8 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -222,13 +235,13 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= +github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= @@ -252,6 +265,7 @@ github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHo github.com/jackc/puddle/v2 v2.0.0/go.mod h1:itE7ZJY8xnoo0JqJEpSMprN0f+NQkMCuEV/N9j8h0oc= github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= @@ -266,8 +280,7 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -277,19 +290,20 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 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 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -299,17 +313,18 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -325,8 +340,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -342,8 +357,6 @@ github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtb github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/ompluscator/dynamic-struct v1.4.0 h1:I/Si9LZtItSwiTMe7vosEuIu2TKdOvWbE3R/lokpN4Q= -github.com/ompluscator/dynamic-struct v1.4.0/go.mod h1:ADQ1+6Ox1D+ntuNwTHyl1NvpAqY2lBXPSPbcO4CJdeA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -379,39 +392,37 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +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-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= -github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -434,7 +445,7 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -469,7 +480,7 @@ github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9a github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -512,6 +523,7 @@ golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -553,15 +565,15 @@ golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= +golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= 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= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -592,14 +604,13 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/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-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -617,8 +628,8 @@ golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -639,13 +650,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -698,6 +708,7 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= diff --git a/packages/services/package.json b/packages/services/package.json index bad3e4eeb9..f6f1589f34 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -41,7 +41,8 @@ "build:js": "tsup", "build:protobuf": "make protoc-ts && prettier --write protobuf/ts/**/*.ts", "dev": "tsup --watch", - "test": "tsc --noEmit && echo 'todo: add tests'" + "test": "pnpm run test:go", + "test:go": "go test -v ./..." }, "dependencies": { "long": "^5.2.1", diff --git a/packages/services/pkg/protocol-parser/abiTypesToSchema.go b/packages/services/pkg/protocol-parser/abiTypesToSchema.go new file mode 100644 index 0000000000..7f12c5ceac --- /dev/null +++ b/packages/services/pkg/protocol-parser/abiTypesToSchema.go @@ -0,0 +1,21 @@ +package protocolparser + +import schematype "latticexyz/mud/packages/services/pkg/schema-type" + +func AbiTypesToSchema(abiTypes []schematype.SchemaType) Schema { + staticFields := []schematype.SchemaType{} + dynamicFields := []schematype.SchemaType{} + + for _, abiType := range abiTypes { + if abiType.IsDynamic() { + dynamicFields = append(dynamicFields, abiType) + } else { + staticFields = append(staticFields, abiType) + } + } + + return Schema{ + StaticFields: staticFields, + DynamicFields: dynamicFields, + } +} diff --git a/packages/services/pkg/protocol-parser/abiTypesToSchema_test.go b/packages/services/pkg/protocol-parser/abiTypesToSchema_test.go new file mode 100644 index 0000000000..63bc57bddb --- /dev/null +++ b/packages/services/pkg/protocol-parser/abiTypesToSchema_test.go @@ -0,0 +1,64 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + . "latticexyz/mud/packages/services/pkg/schema-type" + "reflect" + "testing" +) + +func TestAbiTypesToSchema(testing *testing.T) { + abiTypesList := [][]SchemaType{ + { + BOOL, + }, + { + BOOL, + BOOL_ARRAY, + }, + { + BYTES32, + INT32, + UINT256_ARRAY, + ADDRESS_ARRAY, + BYTES, + STRING, + }, + } + + expectedSchemas := []protocolparser.Schema{ + { + StaticFields: []SchemaType{ + BOOL, + }, + DynamicFields: []SchemaType{}, + }, + { + StaticFields: []SchemaType{ + BOOL, + }, + DynamicFields: []SchemaType{ + BOOL_ARRAY, + }, + }, + { + StaticFields: []SchemaType{ + BYTES32, + INT32, + }, + DynamicFields: []SchemaType{ + UINT256_ARRAY, + ADDRESS_ARRAY, + BYTES, + STRING, + }, + }, + } + + for i, abiTypes := range abiTypesList { + schema := protocolparser.AbiTypesToSchema(abiTypes) + if !reflect.DeepEqual(schema, expectedSchemas[i]) { + testing.Errorf("expected schema to be %v, got %v", expectedSchemas[i], schema) + } + } +} diff --git a/packages/services/pkg/protocol-parser/common.go b/packages/services/pkg/protocol-parser/common.go new file mode 100644 index 0000000000..a466b2f7fd --- /dev/null +++ b/packages/services/pkg/protocol-parser/common.go @@ -0,0 +1,13 @@ +package protocolparser + +import schematype "latticexyz/mud/packages/services/pkg/schema-type" + +type Schema struct { + StaticFields []schematype.SchemaType + DynamicFields []schematype.SchemaType +} + +type TableSchema struct { + KeySchema Schema + ValueSchema Schema +} diff --git a/packages/services/pkg/protocol-parser/decodeDynamicField.go b/packages/services/pkg/protocol-parser/decodeDynamicField.go new file mode 100644 index 0000000000..4238490b86 --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeDynamicField.go @@ -0,0 +1,137 @@ +package protocolparser + +import ( + . "latticexyz/mud/packages/services/pkg/schema-type" + + "github.com/andriidski/abiencode-go/convert" +) + +func DecodeDynamicField(schemaType SchemaType, data string) interface{} { + if schemaType == BYTES { + return convert.HexToBytes(data) + } + if schemaType == STRING { + return convert.HexToString(data) + } + + if len(data) > 3 && len(data)%2 != 0 { + panic(ErrInvalidHexLength) + } + + dataSize := (len(data) - 2) / 2 + + switch schemaType { + case UINT8_ARRAY, + UINT16_ARRAY, + UINT24_ARRAY, + UINT32_ARRAY, + UINT40_ARRAY, + UINT48_ARRAY, + UINT56_ARRAY, + UINT64_ARRAY, + UINT72_ARRAY, + UINT80_ARRAY, + UINT88_ARRAY, + UINT96_ARRAY, + UINT104_ARRAY, + UINT112_ARRAY, + UINT120_ARRAY, + UINT128_ARRAY, + UINT136_ARRAY, + UINT144_ARRAY, + UINT152_ARRAY, + UINT160_ARRAY, + UINT168_ARRAY, + UINT176_ARRAY, + UINT184_ARRAY, + UINT192_ARRAY, + UINT200_ARRAY, + UINT208_ARRAY, + UINT216_ARRAY, + UINT224_ARRAY, + UINT232_ARRAY, + UINT240_ARRAY, + UINT248_ARRAY, + UINT256_ARRAY, + INT8_ARRAY, + INT16_ARRAY, + INT24_ARRAY, + INT32_ARRAY, + INT40_ARRAY, + INT48_ARRAY, + INT56_ARRAY, + INT64_ARRAY, + INT72_ARRAY, + INT80_ARRAY, + INT88_ARRAY, + INT96_ARRAY, + INT104_ARRAY, + INT112_ARRAY, + INT120_ARRAY, + INT128_ARRAY, + INT136_ARRAY, + INT144_ARRAY, + INT152_ARRAY, + INT160_ARRAY, + INT168_ARRAY, + INT176_ARRAY, + INT184_ARRAY, + INT192_ARRAY, + INT200_ARRAY, + INT208_ARRAY, + INT216_ARRAY, + INT224_ARRAY, + INT232_ARRAY, + INT240_ARRAY, + INT248_ARRAY, + INT256_ARRAY, + BYTES1_ARRAY, + BYTES2_ARRAY, + BYTES3_ARRAY, + BYTES4_ARRAY, + BYTES5_ARRAY, + BYTES6_ARRAY, + BYTES7_ARRAY, + BYTES8_ARRAY, + BYTES9_ARRAY, + BYTES10_ARRAY, + BYTES11_ARRAY, + BYTES12_ARRAY, + BYTES13_ARRAY, + BYTES14_ARRAY, + BYTES15_ARRAY, + BYTES16_ARRAY, + BYTES17_ARRAY, + BYTES18_ARRAY, + BYTES19_ARRAY, + BYTES20_ARRAY, + BYTES21_ARRAY, + BYTES22_ARRAY, + BYTES23_ARRAY, + BYTES24_ARRAY, + BYTES25_ARRAY, + BYTES26_ARRAY, + BYTES27_ARRAY, + BYTES28_ARRAY, + BYTES29_ARRAY, + BYTES30_ARRAY, + BYTES31_ARRAY, + BYTES32_ARRAY, + BOOL_ARRAY, + ADDRESS_ARRAY: + staticAbiType := ArrayAbiTypeToStaticAbiType(schemaType) + itemByteLength := staticAbiType.ByteLength() + if dataSize%itemByteLength != 0 { + panic(ErrInvalidHexLengthForArrayField) + } + itemCount := dataSize / int(itemByteLength) + items := make([]interface{}, itemCount) + for i := 0; i < itemCount; i++ { + itemData := HexSlice(data, i*itemByteLength, (i+1)*itemByteLength) + items[i] = DecodeStaticField(staticAbiType, itemData) + } + return items + default: + panic("unsupported type") + } +} diff --git a/packages/services/pkg/protocol-parser/decodeDynamicField_test.go b/packages/services/pkg/protocol-parser/decodeDynamicField_test.go new file mode 100644 index 0000000000..a172fd1b53 --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeDynamicField_test.go @@ -0,0 +1,408 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + schematype "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + "reflect" + "testing" + + "github.com/andriidski/abiencode-go/convert" + "github.com/ethereum/go-ethereum/common" +) + +func TestDecodeDynamicFieldBoolArray(t *testing.T) { + boolArrayData := []string{ + "0x00", + "0x01", + "0x0000", + "0x0001", + "0x0100", + "0x0101", + } + expectedDecodedData := [][]bool{ + {false}, + {true}, + {false, false}, + {false, true}, + {true, false}, + {true, true}, + } + for i, data := range boolArrayData { + decodedData := convert.ToBoolArray(protocolparser.DecodeDynamicField(schematype.BOOL_ARRAY, data)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData[i]) { + t.Errorf("expected %v, got %v", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeDynamicFieldUint8Array(t *testing.T) { + uint8ArrayData := []string{ + "0x00", + "0x01", + "0xff", + "0x0000", + "0x0001", + "0x00ff", + "0x0100", + "0x0101", + "0x01ff", + "0xff00", + "0xff01", + "0xffff", + } + expectedDecodedData := [][]uint8{ + {0}, + {1}, + {255}, + {0, 0}, + {0, 1}, + {0, 255}, + {1, 0}, + {1, 1}, + {1, 255}, + {255, 0}, + {255, 1}, + {255, 255}, + } + for i, data := range uint8ArrayData { + decodedData := convert.ToUint8Array(protocolparser.DecodeDynamicField(schematype.UINT8_ARRAY, data)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData[i]) { + t.Errorf("expected %v, got %v", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeDynamicFieldUint256Array(t *testing.T) { + uint256Data := []string{ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", + "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + } + + expectedDecodedData := [][]*big.Int{ + {big.NewInt(1)}, + {protocolparser.BigIntFromString("115792089237316195423570985008687907853269984665640564039457584007913129639935")}, + {protocolparser.BigIntFromString("115792089237316195423570985008687907853269984665640564039457584007913129639934")}, + {big.NewInt(1), big.NewInt(1)}, + { + protocolparser.BigIntFromString("115792089237316195423570985008687907853269984665640564039457584007913129639935"), + protocolparser.BigIntFromString("115792089237316195423570985008687907853269984665640564039457584007913129639935"), + }, + } + + for i, data := range uint256Data { + decodedData := convert.ToUint256Array(protocolparser.DecodeDynamicField(schematype.UINT256_ARRAY, data)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData[i]) { + t.Errorf("expected %v, got %v", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeDynamicFieldInt8Array(t *testing.T) { + int8ArrayData := []string{ + "0x00", + "0x01", + "0x7f", + "0x80", + "0x81", + "0xff", + "0x0000", + "0x0100", + "0x007f", + "0x8080", + "0x8181", + "0x00ff", + } + expectedDecodedData := [][]int8{ + {0}, + {1}, + {127}, + {-128}, + {-127}, + {-1}, + {0, 0}, + {1, 0}, + {0, 127}, + {-128, -128}, + {-127, -127}, + {0, -1}, + } + for i, data := range int8ArrayData { + decodedData := convert.ToInt8Array(protocolparser.DecodeDynamicField(schematype.INT8_ARRAY, data)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData[i]) { + t.Errorf("expected %v, got %v", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeDynamicFieldInt256Array(t *testing.T) { + int256ArrayData := []string{ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x8000000000000000000000000000000000000000000000000000000000000000", + "0x8000000000000000000000000000000000000000000000000000000000000001", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000000000000000000000000000000000000000000000001", + } + + expectedDecodedData := [][]*big.Int{ + {big.NewInt(0)}, + {big.NewInt(1)}, + {protocolparser.BigIntFromString("57896044618658097711785492504343953926634992332820282019728792003956564819967")}, + {protocolparser.BigIntFromString("-57896044618658097711785492504343953926634992332820282019728792003956564819968")}, + {protocolparser.BigIntFromString("-57896044618658097711785492504343953926634992332820282019728792003956564819967")}, + {big.NewInt(-1)}, + { + protocolparser.BigIntFromString("57896044618658097711785492504343953926634992332820282019728792003956564819967"), + big.NewInt(-1), + }, + { + protocolparser.BigIntFromString("-57896044618658097711785492504343953926634992332820282019728792003956564819968"), + big.NewInt(0), + }, + { + big.NewInt(-1), + protocolparser.BigIntFromString("-57896044618658097711785492504343953926634992332820282019728792003956564819967"), + }, + } + + for i, data := range int256ArrayData { + decodedData := convert.ToInt256Array(protocolparser.DecodeDynamicField(schematype.INT256_ARRAY, data)) + + for j := range decodedData { + if decodedData[j].Cmp(expectedDecodedData[i][j]) != 0 { + t.Errorf("expected value %d, got %d", expectedDecodedData[i][j], decodedData[j]) + t.Errorf("expected array %v, got %v", expectedDecodedData[i], decodedData) + } + } + } +} + +func TestDecodeDynamicFieldBytesArray(t *testing.T) { + bytesArrayData := "0x01" + expectedDecodedData := [][]byte{ + {1}, + } + decodedData := convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES1_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0x0001" + expectedDecodedData = [][]byte{ + {0}, + {1}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES1_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0x0001" + expectedDecodedData = [][]byte{ + {0, 1}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES2_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0xff00ff00ff00ff00" + expectedDecodedData = [][]byte{ + {255, 0, 255, 0, 255, 0, 255, 0}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES8_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0xff00ff00ff00ff00" + expectedDecodedData = [][]byte{ + {255}, + {0}, + {255}, + {0}, + {255}, + {0}, + {255}, + {0}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES1_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0xff00ff00ff00ff00" + expectedDecodedData = [][]byte{ + {255, 0}, + {255, 0}, + {255, 0}, + {255, 0}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES2_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0xff00ff00ff00ff00" + expectedDecodedData = [][]byte{ + {255, 0, 255, 0}, + {255, 0, 255, 0}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES4_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0x0000000000000000000000000000000000000000000000000000000000000001" + expectedDecodedData = [][]byte{ + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {1}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES1_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + expectedDecodedData = [][]byte{ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES32_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + bytesArrayData = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + expectedDecodedData = [][]byte{ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + } + decodedData = convert.ToBytesArray(protocolparser.DecodeDynamicField(schematype.BYTES32_ARRAY, bytesArrayData)) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } +} + +func TestDecodeDynamicFieldAddressArray(t *testing.T) { + addressArrayData := []string{ + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + } + expectedDecodedData := []common.Address{ + common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"), + } + decodedData := convert.ToAddressArray(protocolparser.DecodeDynamicField(schematype.ADDRESS_ARRAY, addressArrayData[0])) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } + + addressArrayData = []string{ + "0xffffffffffffffffffffffffffffffffffffffff", + } + expectedDecodedData = []common.Address{ + common.HexToAddress("0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF"), + } + decodedData = convert.ToAddressArray(protocolparser.DecodeDynamicField(schematype.ADDRESS_ARRAY, addressArrayData[0])) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %v, got %v", expectedDecodedData, decodedData) + } +} + +func TestDecodeDynamicFieldBytes(t *testing.T) { + bytesData := []string{ + "0x", + "0x00", + "0x01", + "0x0001", + "0xff00ff00ff00ff00", + "0x0000000000000000000000000000000000000000000000000000000000000001", + } + + expectedDecodedData := [][]byte{ + {}, + {0}, + {1}, + {0, 1}, + {255, 0, 255, 0, 255, 0, 255, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + } + + for i, data := range bytesData { + decodedData := protocolparser.DecodeDynamicField(schematype.BYTES, data) + + if !reflect.DeepEqual(decodedData, expectedDecodedData[i]) { + t.Errorf("expected %v, got %v", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeDynamicFieldString(t *testing.T) { + stringData := []string{ + "0x", + "0x68656c6c6f", + } + + expectedDecodedData := []string{ + "", + "hello", + } + + for i, data := range stringData { + decodedData := protocolparser.DecodeDynamicField(schematype.STRING, data) + + if !reflect.DeepEqual(decodedData, expectedDecodedData[i]) { + t.Errorf("expected %v, got %v", expectedDecodedData[i], decodedData) + } + } +} diff --git a/packages/services/pkg/protocol-parser/decodeField.go b/packages/services/pkg/protocol-parser/decodeField.go new file mode 100644 index 0000000000..fcf71875aa --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeField.go @@ -0,0 +1,11 @@ +package protocolparser + +import schematype "latticexyz/mud/packages/services/pkg/schema-type" + +func DecodeField(schemaType schematype.SchemaType, data string) interface{} { + if schemaType.IsDynamic() { + return DecodeDynamicField(schemaType, data) + } else { + return DecodeStaticField(schemaType, data) + } +} diff --git a/packages/services/pkg/protocol-parser/decodeKeyTuple.go b/packages/services/pkg/protocol-parser/decodeKeyTuple.go new file mode 100644 index 0000000000..04cd33b722 --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeKeyTuple.go @@ -0,0 +1,43 @@ +package protocolparser + +import ( + "strings" + + abi_geth "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +func decodeAbiParameters(types []string, hexData string) []interface{} { + args := make(abi_geth.Arguments, 0) + + for _, _type := range types { + + arg := abi_geth.Argument{} + var err error + arg.Type, err = abi_geth.NewType(_type, "", nil) + if err != nil { + panic(err) + } + args = append(args, arg) + } + + bytes, err := hexutil.Decode(hexData) + if err != nil { + panic(err) + } + + decoding, err := args.UnpackValues(bytes) + if err != nil { + panic(err) + } + return decoding +} + +func DecodeKeyTuple(keySchema Schema, keyTuple []string) []interface{} { + decoded := make([]interface{}, 0) + for i, _type := range keySchema.StaticFields { + abiType := strings.ToLower(_type.String()) + decoded = append(decoded, decodeAbiParameters([]string{abiType}, keyTuple[i])[0]) + } + return decoded +} diff --git a/packages/services/pkg/protocol-parser/decodeKeyTuple_test.go b/packages/services/pkg/protocol-parser/decodeKeyTuple_test.go new file mode 100644 index 0000000000..ce7028cb2e --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeKeyTuple_test.go @@ -0,0 +1,81 @@ +package protocolparser_test + +import ( + "math/big" + "reflect" + "testing" + + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + schematype "latticexyz/mud/packages/services/pkg/schema-type" + + "github.com/ethereum/go-ethereum/common" +) + +func TestDecodeKeyTupleBool(t *testing.T) { + schemas := []protocolparser.Schema{ + { + StaticFields: []schematype.SchemaType{ + schematype.BOOL, + }, + }, + { + StaticFields: []schematype.SchemaType{ + schematype.BOOL, + }, + }, + } + hexTuples := [][]string{ + {"0x0000000000000000000000000000000000000000000000000000000000000000"}, + {"0x0000000000000000000000000000000000000000000000000000000000000001"}, + } + expectedDecodedData := [][]interface{}{ + {false}, + {true}, + } + + for i, schema := range schemas { + decodedData := protocolparser.DecodeKeyTuple(schema, hexTuples[i]) + if decodedData[0].(bool) != expectedDecodedData[i][0] { + t.Errorf("expected %v, got %v", expectedDecodedData[i][0], decodedData[0]) + } + } +} + +func TestDecodeKeyTupleComplex(t *testing.T) { + schema := protocolparser.Schema{ + StaticFields: []schematype.SchemaType{ + schematype.UINT256, + schematype.INT32, + schematype.BYTES16, + schematype.ADDRESS, + schematype.BOOL, + schematype.INT8, + }, + } + + hexTuple := []string{ + "0x000000000000000000000000000000000000000000000000000000000000002a", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6", + "0x1234000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000003", + } + + expectedDecodedData := []interface{}{ + big.NewInt(42), + int32(-42), + [16]byte{0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + common.HexToAddress("0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF"), + true, + int8(3), + } + + decodedData := protocolparser.DecodeKeyTuple(schema, hexTuple) + + for i, data := range decodedData { + if !reflect.DeepEqual(data, expectedDecodedData[i]) { + t.Errorf("expected %v, got %v", expectedDecodedData[i], data) + } + } +} diff --git a/packages/services/pkg/protocol-parser/decodeRecord.go b/packages/services/pkg/protocol-parser/decodeRecord.go new file mode 100644 index 0000000000..f1ad062487 --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeRecord.go @@ -0,0 +1,42 @@ +package protocolparser + +import "fmt" + +func DecodeRecord(schema Schema, data string) []interface{} { + values := []interface{}{} + + bytesOffset := 0 + for _, fieldType := range schema.StaticFields { + fieldByteLength := fieldType.ByteLength() + value := DecodeStaticField(fieldType, HexSlice(data, bytesOffset, bytesOffset+fieldByteLength)) + bytesOffset += fieldByteLength + values = append(values, value) + } + + // Warn user if static data length does not match the schema, because data corruption might be possible + schemaStaticDataLength := StaticDataLength(schema.StaticFields) + actualStaticDataLength := bytesOffset + if schemaStaticDataLength != actualStaticDataLength { + println(fmt.Sprintf("warning: schema static data length (%d) does not match actual static data length (%d)", schemaStaticDataLength, actualStaticDataLength)) + } + + if len(schema.DynamicFields) > 0 { + dataLayout := HexToPackedCounter(HexSlice(data, bytesOffset, bytesOffset+32)) + bytesOffset += 32 + + for i, fieldType := range schema.DynamicFields { + dataLength := dataLayout.FieldByteLengths[i] + value := DecodeDynamicField(fieldType, HexSlice(data, bytesOffset, bytesOffset+int(dataLength))) + bytesOffset += int(dataLength) + values = append(values, value) + } + + // Warn user if dynamic data length does not match the schema, because data corruption might be possible + actualDynamicDataLength := bytesOffset - 32 - actualStaticDataLength + if uint64(actualDynamicDataLength) != dataLayout.TotalByteLength { + println(fmt.Sprintf("warning: schema dynamic data length (%d) does not match actual dynamic data length (%d)", dataLayout.TotalByteLength, actualDynamicDataLength)) + } + } + + return values +} diff --git a/packages/services/pkg/protocol-parser/decodeRecord_test.go b/packages/services/pkg/protocol-parser/decodeRecord_test.go new file mode 100644 index 0000000000..e0018db9ef --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeRecord_test.go @@ -0,0 +1,48 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + schematype "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + "reflect" + "testing" + + "github.com/andriidski/abiencode-go/convert" +) + +func TestDecodeRecord(t *testing.T) { + schema := protocolparser.Schema{ + StaticFields: []schematype.SchemaType{ + schematype.UINT32, + schematype.UINT128, + }, + DynamicFields: []schematype.SchemaType{ + schematype.UINT32_ARRAY, + schematype.STRING, + }, + } + + hex := "0x0000000100000000000000000000000000000002000000000000130000000008000000000b0000000000000000000000000000000000000300000004736f6d6520737472696e67" + + expectedDecodedData := []interface{}{ + uint32(1), + big.NewInt(2), + []uint32{3, 4}, + "some string", + } + + decodedData := protocolparser.DecodeRecord(schema, hex) + if decodedData[0].(uint32) != expectedDecodedData[0] { + t.Errorf("expected %v, got %v", expectedDecodedData[0], decodedData[0]) + } + if decodedData[1].(*big.Int).Cmp(expectedDecodedData[1].(*big.Int)) != 0 { + t.Errorf("expected %v, got %v", expectedDecodedData[1], decodedData[1]) + } + array := convert.ToUint32Array(decodedData[2]) + if !reflect.DeepEqual(array, expectedDecodedData[2]) { + t.Errorf("expected %v, got %v", expectedDecodedData[2], array) + } + if decodedData[3].(string) != expectedDecodedData[3] { + t.Errorf("expected %v, got %v", expectedDecodedData[3], decodedData[3]) + } +} diff --git a/packages/services/pkg/protocol-parser/decodeStaticField.go b/packages/services/pkg/protocol-parser/decodeStaticField.go new file mode 100644 index 0000000000..90c16afb23 --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeStaticField.go @@ -0,0 +1,133 @@ +package protocolparser + +import ( + . "latticexyz/mud/packages/services/pkg/schema-type" + + "github.com/andriidski/abiencode-go/convert" +) + +func DecodeStaticField(schemaType SchemaType, data string) interface{} { + if len(data) > 3 && len(data)%2 != 0 { + panic(ErrInvalidHexLength) + } + + dataSize := (len(data) - 2) / 2 + if dataSize != StaticAbiTypeToByteLength(schemaType) { + panic(ErrInvalidHexLengthForStaticField) + } + + switch schemaType { + case UINT8: + return convert.HexToUint8(data) + case UINT16: + return convert.HexToUint16(data) + case UINT24, UINT32: + return convert.HexToUint32(data) + case UINT40, + UINT48, + UINT56, + UINT64: + return convert.HexToUint64(data) + case UINT72, + UINT80, + UINT88, + UINT96, + UINT104, + UINT112, + UINT120, + UINT128, + UINT136, + UINT144, + UINT152, + UINT160, + UINT168, + UINT176, + UINT184, + UINT192, + UINT200, + UINT208, + UINT216, + UINT224, + UINT232, + UINT240, + UINT248, + UINT256: + return convert.HexToBigInt(data) + case INT8: + return convert.HexToInt8(data) + case INT16: + return convert.HexToInt16(data) + case INT24, INT32: + return convert.HexToInt32(data) + case INT40, + INT48, + INT56, + INT64: + return convert.HexToInt64(data) + case INT72, + INT80, + INT88, + INT96, + INT104, + INT112, + INT120, + INT128, + INT136, + INT144, + INT152, + INT160, + INT168, + INT176, + INT184, + INT192, + INT200, + INT208, + INT216, + INT224, + INT232, + INT240, + INT248, + INT256: + return convert.HexToBigIntSigned(data) + case BYTES1, + BYTES2, + BYTES3, + BYTES4, + BYTES5, + BYTES6, + BYTES7, + BYTES8, + BYTES9, + BYTES10, + BYTES11, + BYTES12, + BYTES13, + BYTES14, + BYTES15, + BYTES16, + BYTES17, + BYTES18, + BYTES19, + BYTES20, + BYTES21, + BYTES22, + BYTES23, + BYTES24, + BYTES25, + BYTES26, + BYTES27, + BYTES28, + BYTES29, + BYTES30, + BYTES31, + BYTES32: + // TODO: should we return a fixed size array per bytes size or a slice? + return convert.HexToBytes(data) + case BOOL: + return convert.HexToBool(data) + case ADDRESS: + return convert.HexToAddress(data) + default: + panic("unsupported type") + } +} diff --git a/packages/services/pkg/protocol-parser/decodeStaticField_test.go b/packages/services/pkg/protocol-parser/decodeStaticField_test.go new file mode 100644 index 0000000000..7d1bc8eb6a --- /dev/null +++ b/packages/services/pkg/protocol-parser/decodeStaticField_test.go @@ -0,0 +1,347 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + schematype "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + "reflect" + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +func TestDecodeStaticFieldBool(t *testing.T) { + if protocolparser.DecodeStaticField(schematype.BOOL, "0x00") != false { + t.Error("expected false") + } + if protocolparser.DecodeStaticField(schematype.BOOL, "0x01") != true { + t.Error("expected true") + } +} + +func TestDecodeStaticFieldUint8(t *testing.T) { + uint8Data := []string{ + "0x00", + "0x01", + "0xff", + } + + expectedDecodedData := []uint8{ + uint8(0), + uint8(1), + uint8(255), + } + + for i, data := range uint8Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT8, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } + +} + +func TestDecodeStaticFieldUint16(t *testing.T) { + uint16Data := []string{ + "0x0000", + "0x0001", + "0xffff", + } + + expectedDecodedData := []uint16{ + uint16(0), + uint16(1), + uint16(65535), + } + + for i, data := range uint16Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT16, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldUint24(t *testing.T) { + uint24Data := []string{ + "0x000000", + "0x000001", + "0xffffff", + } + + expectedDecodedData := []uint32{ + uint32(0), + uint32(1), + uint32(16777215), + } + + for i, data := range uint24Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT24, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldUint32(t *testing.T) { + uint32Data := []string{ + "0x00000000", + "0x00000001", + "0xffffffff", + } + + expectedDecodedData := []uint32{ + uint32(0), + uint32(1), + uint32(4294967295), + } + + for i, data := range uint32Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT32, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldUint40(t *testing.T) { + uint40Data := []string{ + "0x0000000000", + "0x0000000001", + "0xffffffffff", + } + + expectedDecodedData := []uint64{ + uint64(0), + uint64(1), + uint64(1099511627775), + } + + for i, data := range uint40Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT40, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldUint48(t *testing.T) { + uint48Data := []string{ + "0x000000000000", + "0x000000000001", + "0xffffffffffff", + } + + expectedDecodedData := []uint64{ + uint64(0), + uint64(1), + uint64(281474976710655), + } + + for i, data := range uint48Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT48, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldUint56(t *testing.T) { + uint56Data := []string{ + "0x00000000000000", + "0x00000000000001", + "0xffffffffffffff", + } + + expectedDecodedData := []uint64{ + uint64(0), + uint64(1), + uint64(72057594037927935), + } + + for i, data := range uint56Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT56, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldUint64(t *testing.T) { + uint64Data := []string{ + "0x0000000000000000", + "0x0000000000000001", + "0xffffffffffffffff", + } + + expectedDecodedData := []uint64{ + uint64(0), + uint64(1), + uint64(18446744073709551615), + } + + for i, data := range uint64Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT64, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldUint256(t *testing.T) { + uint256Data := []string{ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + } + + max, _ := big.NewInt(0).SetString("115792089237316195423570985008687907853269984665640564039457584007913129639935", 10) + expectedDecodedData := []*big.Int{ + big.NewInt(0), + big.NewInt(1), + max, + } + + for i, data := range uint256Data { + decodedData := protocolparser.DecodeStaticField(schematype.UINT256, data) + if decodedData.(*big.Int).Cmp(expectedDecodedData[i]) != 0 { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldInt8(t *testing.T) { + int8Data := []string{ + "0x00", + "0x01", + "0x7f", + "0xff", + "0x80", + "0x81", + } + + expectedDecodedData := []int8{ + int8(0), + int8(1), + int8(127), + int8(-1), + int8(-128), + int8(-127), + } + + for i, data := range int8Data { + decodedData := protocolparser.DecodeStaticField(schematype.INT8, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + + } +} + +func TestDecodeStaticFieldInt256(t *testing.T) { + int256Data := []string{ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x8000000000000000000000000000000000000000000000000000000000000000", + "0x8000000000000000000000000000000000000000000000000000000000000001", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + } + + expectedDecodedData := []*big.Int{ + big.NewInt(0), + big.NewInt(1), + protocolparser.BigIntFromString("57896044618658097711785492504343953926634992332820282019728792003956564819967"), + protocolparser.BigIntFromString("-57896044618658097711785492504343953926634992332820282019728792003956564819968"), + protocolparser.BigIntFromString("-57896044618658097711785492504343953926634992332820282019728792003956564819967"), + big.NewInt(-1), + } + + for i, data := range int256Data { + decodedData := protocolparser.DecodeStaticField(schematype.INT256, data) + if decodedData.(*big.Int).Cmp(expectedDecodedData[i]) != 0 { + t.Errorf("expected %d, got %d", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldBytes(t *testing.T) { + bytesData := "0x01" + expectedDecodedData := []byte{1} + decodedData := protocolparser.DecodeStaticField(schematype.BYTES1, bytesData) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %d, got %d", expectedDecodedData, decodedData) + } + + bytesData = "0x0001" + expectedDecodedData = []byte{0, 1} + decodedData = protocolparser.DecodeStaticField(schematype.BYTES2, bytesData) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %d, got %d", expectedDecodedData, decodedData) + } + + bytesData = "0xff00ff00ff00ff00" + expectedDecodedData = []byte{255, 0, 255, 0, 255, 0, 255, 0} + decodedData = protocolparser.DecodeStaticField(schematype.BYTES8, bytesData) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %d, got %d", expectedDecodedData, decodedData) + } + + bytesData = "0x0000000000000000000000000000000000000000000000000000000000000001" + expectedDecodedData = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + decodedData = protocolparser.DecodeStaticField(schematype.BYTES32, bytesData) + + if !reflect.DeepEqual(decodedData, expectedDecodedData) { + t.Errorf("expected %d, got %d", expectedDecodedData, decodedData) + } +} + +func TestDecodeStaticFieldAddress(t *testing.T) { + addressData := []string{ + "0xf3958f7F68875735c24424D554eB46ddF8e8eD33", + "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF", + } + + expectedDecodedData := []common.Address{ + common.HexToAddress("0xf3958f7f68875735c24424d554eb46ddf8e8ed33"), + common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff"), + } + + for i, data := range addressData { + decodedData := protocolparser.DecodeStaticField(schematype.ADDRESS, data) + if decodedData != expectedDecodedData[i] { + t.Errorf("expected %s, got %s", expectedDecodedData[i], decodedData) + } + } +} + +func TestDecodeStaticFieldInvalidHexLengthForStaticField(t *testing.T) { + defer func() { + err := recover().(error) + + if err.Error() != protocolparser.ErrInvalidHexLengthForStaticField.Error() { + t.Fatalf("wrong panic message: %s", err.Error()) + } + }() + + data := "0x1" + protocolparser.DecodeStaticField(schematype.BOOL, data) + t.Error("expected panic") +} + +func TestDecodeStaticFieldInvalidHexLength(t *testing.T) { + defer func() { + err := recover().(error) + + if err.Error() != protocolparser.ErrInvalidHexLength.Error() { + t.Fatalf("wrong panic message: %s", err.Error()) + } + }() + + data := "0x001" + protocolparser.DecodeStaticField(schematype.BOOL, data) + t.Error("expected panic") +} diff --git a/packages/services/pkg/protocol-parser/encodeField.go b/packages/services/pkg/protocol-parser/encodeField.go new file mode 100644 index 0000000000..628cf0f6c6 --- /dev/null +++ b/packages/services/pkg/protocol-parser/encodeField.go @@ -0,0 +1,28 @@ +package protocolparser + +import ( + schematype "latticexyz/mud/packages/services/pkg/schema-type" + + "github.com/andriidski/abiencode-go/abi" +) + +func IsArray(value interface{}) bool { + _, ok := value.([]interface{}) + return ok +} + +func EncodeField(fieldType schematype.SchemaType, value interface{}) string { + if fieldType.IsArray() { + staticFieldType := schematype.ArrayAbiTypeToStaticAbiType(fieldType) + valueArr, ok := value.([]interface{}) + if !ok { + panic("value is not an array") + } + staticFieldTypeArr := make([]schematype.SchemaType, len(valueArr)) + for i := range valueArr { + staticFieldTypeArr[i] = staticFieldType + } + return abi.EncodePacked(SchemaTypesToStringTypes(staticFieldTypeArr), valueArr) + } + return abi.EncodePacked(SchemaTypesToStringTypes([]schematype.SchemaType{fieldType}), []interface{}{value}) +} diff --git a/packages/services/pkg/protocol-parser/encodeKeyTuple.go b/packages/services/pkg/protocol-parser/encodeKeyTuple.go new file mode 100644 index 0000000000..ecff727529 --- /dev/null +++ b/packages/services/pkg/protocol-parser/encodeKeyTuple.go @@ -0,0 +1,18 @@ +package protocolparser + +import ( + schematype "latticexyz/mud/packages/services/pkg/schema-type" + + "github.com/andriidski/abiencode-go/abi" +) + +func EncodeKeyTuple(keySchema Schema, keyTuple []interface{}) []string { + encodings := []string{} + for i, key := range keyTuple { + encodings = append(encodings, abi.Encode( + SchemaTypesToStringTypes([]schematype.SchemaType{keySchema.StaticFields[i]}), + []interface{}{key}, + )) + } + return encodings +} diff --git a/packages/services/pkg/protocol-parser/encodeKeyTuple_test.go b/packages/services/pkg/protocol-parser/encodeKeyTuple_test.go new file mode 100644 index 0000000000..4e3360a761 --- /dev/null +++ b/packages/services/pkg/protocol-parser/encodeKeyTuple_test.go @@ -0,0 +1,66 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + . "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + "reflect" + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +func TestEncodeKeyTupleBool(t *testing.T) { + keySchema := protocolparser.Schema{ + StaticFields: []SchemaType{ + BOOL, + }, + DynamicFields: []SchemaType{}, + } + keyTuple := []interface{}{ + false, + } + expectedEncoding := []string{ + "0x0000000000000000000000000000000000000000000000000000000000000000", + } + encoding := protocolparser.EncodeKeyTuple(keySchema, keyTuple) + + if !reflect.DeepEqual(encoding, expectedEncoding) { + t.Errorf("expected %v, got %v", expectedEncoding, encoding) + } +} + +func TestEncodeKeyTupleComplex(t *testing.T) { + keySchema := protocolparser.Schema{ + StaticFields: []SchemaType{ + UINT256, + INT32, + BYTES16, + ADDRESS, + BOOL, + INT8, + }, + DynamicFields: []SchemaType{}, + } + keyTuple := []interface{}{ + big.NewInt(42), + int32(-42), + [16]byte{0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + common.HexToAddress("0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF"), + true, + int8(3), + } + expectedEncoding := []string{ + "0x000000000000000000000000000000000000000000000000000000000000002a", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6", + "0x1234000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000003", + } + encoding := protocolparser.EncodeKeyTuple(keySchema, keyTuple) + + if !reflect.DeepEqual(encoding, expectedEncoding) { + t.Errorf("expected %v, got %v", expectedEncoding, encoding) + } +} diff --git a/packages/services/pkg/protocol-parser/encodeRecord.go b/packages/services/pkg/protocol-parser/encodeRecord.go new file mode 100644 index 0000000000..4c80331feb --- /dev/null +++ b/packages/services/pkg/protocol-parser/encodeRecord.go @@ -0,0 +1,58 @@ +package protocolparser + +import ( + schematype "latticexyz/mud/packages/services/pkg/schema-type" + "regexp" + "strings" + + godash "github.com/golodash/godash/strings" +) + +func EncodeRecord(schema Schema, values []interface{}) string { + staticValues := values[0:len(schema.StaticFields)] + dynamicValues := values[len(schema.StaticFields):] + + m1 := regexp.MustCompile(`^0x`) + + staticDataItems := []string{} + for i, staticField := range schema.StaticFields { + encoding := EncodeField(staticField, staticValues[i]) + encoding = m1.ReplaceAllString(encoding, "") + staticDataItems = append(staticDataItems, encoding) + } + staticData := strings.Join(staticDataItems, "") + + if len(schema.DynamicFields) == 0 { + return "0x" + staticData + } + + dynamicDataItems := []string{} + for i, dynamicField := range schema.DynamicFields { + encoding := EncodeField(dynamicField, dynamicValues[i]) + encoding = m1.ReplaceAllString(encoding, "") + dynamicDataItems = append(dynamicDataItems, encoding) + } + + dynamicFieldByteLengths := []int{} + for _, value := range dynamicDataItems { + dynamicFieldByteLengths = append(dynamicFieldByteLengths, len(value)/2) + } + dynamicTotalByteLength := 0 + for _, length := range dynamicFieldByteLengths { + dynamicTotalByteLength += length + } + + dynamicData := strings.Join(dynamicDataItems, "") + + packedCounter := "" + encodedDynamicTotalByteLength := EncodeField(schematype.UINT56, uint64(dynamicTotalByteLength)) + packedCounter += m1.ReplaceAllString(encodedDynamicTotalByteLength, "") + + for _, length := range dynamicFieldByteLengths { + encodedLength := EncodeField(schematype.UINT40, uint64(length)) + packedCounter += m1.ReplaceAllString(encodedLength, "") + } + packedCounter = godash.PadEnd(packedCounter, 64, "0") + + return "0x" + staticData + packedCounter + dynamicData +} diff --git a/packages/services/pkg/protocol-parser/encodeRecord_test.go b/packages/services/pkg/protocol-parser/encodeRecord_test.go new file mode 100644 index 0000000000..c639dd36b5 --- /dev/null +++ b/packages/services/pkg/protocol-parser/encodeRecord_test.go @@ -0,0 +1,56 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + . "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + "testing" +) + +func TestEncodeRecord(t *testing.T) { + schema := protocolparser.Schema{ + StaticFields: []SchemaType{ + UINT32, + UINT128, + }, + DynamicFields: []SchemaType{ + UINT32_ARRAY, + STRING, + }, + } + + hex := protocolparser.EncodeRecord(schema, []interface{}{ + uint32(1), + big.NewInt(2), + []interface{}{ + uint32(3), + uint32(4), + }, + "some string", + }) + expectedHex := "0x0000000100000000000000000000000000000002000000000000130000000008000000000b0000000000000000000000000000000000000300000004736f6d6520737472696e67" + + if hex != expectedHex { + t.Errorf("expected %v, got %v", expectedHex, hex) + } +} + +func TestEncodeRecordNoDynamicFields(t *testing.T) { + schema := protocolparser.Schema{ + StaticFields: []SchemaType{ + UINT32, + UINT128, + }, + DynamicFields: []SchemaType{}, + } + + hex := protocolparser.EncodeRecord(schema, []interface{}{ + uint32(1), + big.NewInt(2), + }) + expectedHex := "0x0000000100000000000000000000000000000002" + + if hex != expectedHex { + t.Errorf("expected %v, got %v", expectedHex, hex) + } +} diff --git a/packages/services/pkg/protocol-parser/errors.go b/packages/services/pkg/protocol-parser/errors.go new file mode 100644 index 0000000000..f42b0d4dad --- /dev/null +++ b/packages/services/pkg/protocol-parser/errors.go @@ -0,0 +1,12 @@ +package protocolparser + +import "errors" + +var ErrInvalidHexLength = errors.New("hex value is an odd length, but must be an even length") +var ErrInvalidHexLengthForSchema = errors.New("hex value must be a length of 64 for a schema") +var ErrInvalidHexLengthForPackedCounter = errors.New("hex value must be a length of 64 for a packed counter") +var ErrInvalidHexLengthForStaticField = errors.New("invalid hex length for static field") +var ErrInvalidHexLengthForArrayField = errors.New("invalid hex length for array field") +var ErrSchemaStaticLengthMismatch = errors.New("schema static length mismatch") +var ErrPackedCounterLengthMismatch = errors.New("packed counter length mismatch") +var ErrAbiEncodingLengthMismatchError = errors.New("abi encoding length mismatch") diff --git a/packages/services/pkg/protocol-parser/hexToPackedCounter.go b/packages/services/pkg/protocol-parser/hexToPackedCounter.go new file mode 100644 index 0000000000..49132ea044 --- /dev/null +++ b/packages/services/pkg/protocol-parser/hexToPackedCounter.go @@ -0,0 +1,35 @@ +package protocolparser + +import ( + schematype "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + + "github.com/andriidski/abiencode-go/convert" +) + +type PackedCounter struct { + TotalByteLength uint64 + FieldByteLengths []uint64 +} + +func HexToPackedCounter(data string) PackedCounter { + if len(data) != 66 { + panic(ErrInvalidHexLengthForPackedCounter) + } + + totalByteLength := DecodeStaticField(schematype.UINT56, HexSlice(data, 0, 7)).(uint64) + fieldByteLengths := convert.ToUint64Array(DecodeDynamicField(schematype.UINT40_ARRAY, HexSliceFrom(data, 7))) + + summedLength := new(big.Int) + for _, length := range fieldByteLengths { + summedLength.Add(summedLength, new(big.Int).SetUint64(length)) + } + if summedLength.Cmp(new(big.Int).SetUint64(totalByteLength)) != 0 { + panic(ErrPackedCounterLengthMismatch) + } + + return PackedCounter{ + TotalByteLength: totalByteLength, + FieldByteLengths: fieldByteLengths, + } +} diff --git a/packages/services/pkg/protocol-parser/hexToPackedCounter_test.go b/packages/services/pkg/protocol-parser/hexToPackedCounter_test.go new file mode 100644 index 0000000000..21065a7f83 --- /dev/null +++ b/packages/services/pkg/protocol-parser/hexToPackedCounter_test.go @@ -0,0 +1,53 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + "reflect" + "testing" +) + +func TestHexToPackedCounter(t *testing.T) { + hex := "0x0000000000008000000000200000000020000000004000000000000000000000" + expectedCounter := protocolparser.PackedCounter{ + TotalByteLength: uint64(128), + FieldByteLengths: []uint64{ + uint64(32), + uint64(32), + uint64(64), + uint64(0), + uint64(0), + }, + } + + if !reflect.DeepEqual(protocolparser.HexToPackedCounter(hex), expectedCounter) { + t.Errorf("expected %v, got %v", expectedCounter, protocolparser.HexToPackedCounter(hex)) + } +} + +func TestHexToPackedCounterInvalidHexData(t *testing.T) { + defer func() { + err := recover().(error) + + if err.Error() != protocolparser.ErrInvalidHexLengthForPackedCounter.Error() { + t.Fatalf("wrong panic message: %s", err.Error()) + } + }() + + hex := "0x01234" + protocolparser.HexToPackedCounter(hex) + t.Error("expected panic") +} + +func TestHexToPackedCounterLengthMismatch(t *testing.T) { + defer func() { + err := recover().(error) + + if err.Error() != protocolparser.ErrPackedCounterLengthMismatch.Error() { + t.Fatalf("wrong panic message: %s", err.Error()) + } + }() + + hex := "0x0000000000004000000000200000000020000000004000000000000000000000" + protocolparser.HexToPackedCounter(hex) + t.Error("expected panic") +} diff --git a/packages/services/pkg/protocol-parser/hexToSchema.go b/packages/services/pkg/protocol-parser/hexToSchema.go new file mode 100644 index 0000000000..809822b28e --- /dev/null +++ b/packages/services/pkg/protocol-parser/hexToSchema.go @@ -0,0 +1,39 @@ +package protocolparser + +import ( + schematype "latticexyz/mud/packages/services/pkg/schema-type" +) + +func HexToSchema(data string) Schema { + if len(data) != 66 { + panic(ErrInvalidHexLengthForSchema) + } + + staticDataLength := HexToNumber(HexSlice(data, 0, 2)) + numStaticFields := HexToNumber(HexSlice(data, 2, 3)) + numDynamicFields := HexToNumber(HexSlice(data, 3, 4)) + + staticFields := []schematype.SchemaType{} + dynamicFields := []schematype.SchemaType{} + + for i := 4; i < 4+numStaticFields; i++ { + staticFields = append(staticFields, schematype.SchemaType(HexToNumber(HexSlice(data, i, i+1)))) + } + for i := 4 + numStaticFields; i < 4+numStaticFields+numDynamicFields; i++ { + dynamicFields = append(dynamicFields, schematype.SchemaType(HexToNumber(HexSlice(data, i, i+1)))) + } + + // Validate static data length + actualStaticData := 0 + for _, field := range staticFields { + actualStaticData += schematype.StaticAbiTypeToByteLength(field) + } + if actualStaticData != staticDataLength { + panic(ErrSchemaStaticLengthMismatch) + } + + return Schema{ + StaticFields: staticFields, + DynamicFields: dynamicFields, + } +} diff --git a/packages/services/pkg/protocol-parser/hexToSchema_test.go b/packages/services/pkg/protocol-parser/hexToSchema_test.go new file mode 100644 index 0000000000..a9a097039e --- /dev/null +++ b/packages/services/pkg/protocol-parser/hexToSchema_test.go @@ -0,0 +1,83 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + . "latticexyz/mud/packages/services/pkg/schema-type" + "reflect" + "testing" +) + +func TestHexToSchema(t *testing.T) { + hexes := []string{ + "0x0001010060000000000000000000000000000000000000000000000000000000", + "0x0001010160c20000000000000000000000000000000000000000000000000000", + "0x002402045f2381c3c4c500000000000000000000000000000000000000000000", + } + + expectedSchemas := []protocolparser.Schema{ + { + StaticFields: []SchemaType{ + BOOL, + }, + DynamicFields: []SchemaType{}, + }, + { + StaticFields: []SchemaType{ + BOOL, + }, + DynamicFields: []SchemaType{ + BOOL_ARRAY, + }, + }, + { + StaticFields: []SchemaType{ + BYTES32, + INT32, + }, + DynamicFields: []SchemaType{ + UINT256_ARRAY, + ADDRESS_ARRAY, + BYTES, + STRING, + }, + }, + } + + for i, hex := range hexes { + schema := protocolparser.HexToSchema(hex) + if !reflect.DeepEqual(schema.StaticFields, expectedSchemas[i].StaticFields) { + t.Errorf("Expected static fields to be %v, got %v", expectedSchemas[i].StaticFields, schema.StaticFields) + } + if !reflect.DeepEqual(schema.DynamicFields, expectedSchemas[i].DynamicFields) { + t.Errorf("Expected dynamic fields to be %v, got %v", expectedSchemas[i].DynamicFields, schema.DynamicFields) + } + } +} + +func TestHexToSchemaInvalidLength(t *testing.T) { + defer func() { + err := recover().(error) + + if err.Error() != protocolparser.ErrInvalidHexLengthForSchema.Error() { + t.Fatalf("wrong panic message: %s", err.Error()) + } + }() + + schemaHex := "0x002502045f2381c3c4c5" + schema := protocolparser.HexToSchema(schemaHex) + t.Errorf("expected to panic, got %v", schema) +} + +func TestHexToSchemaStaticLengthMismatch(t *testing.T) { + defer func() { + err := recover().(error) + + if err.Error() != protocolparser.ErrSchemaStaticLengthMismatch.Error() { + t.Fatalf("wrong panic message: %s", err.Error()) + } + }() + + schemaHex := "0x002502045f2381c3c4c500000000000000000000000000000000000000000000" + schema := protocolparser.HexToSchema(schemaHex) + t.Errorf("expected to panic, got %v", schema) +} diff --git a/packages/services/pkg/protocol-parser/hexToTableSchema.go b/packages/services/pkg/protocol-parser/hexToTableSchema.go new file mode 100644 index 0000000000..eec76fd640 --- /dev/null +++ b/packages/services/pkg/protocol-parser/hexToTableSchema.go @@ -0,0 +1,11 @@ +package protocolparser + +func HexToTableSchema(data string) TableSchema { + valueSchema := HexToSchema(HexSlice(data, 0, 32)) + keySchema := HexToSchema(HexSlice(data, 32, 64)) + + return TableSchema{ + KeySchema: keySchema, + ValueSchema: valueSchema, + } +} diff --git a/packages/services/pkg/protocol-parser/schemaIndexToAbiType.go b/packages/services/pkg/protocol-parser/schemaIndexToAbiType.go new file mode 100644 index 0000000000..e6e6302e16 --- /dev/null +++ b/packages/services/pkg/protocol-parser/schemaIndexToAbiType.go @@ -0,0 +1,10 @@ +package protocolparser + +import schematype "latticexyz/mud/packages/services/pkg/schema-type" + +func SchemaIndexToAbiType(schema Schema, schemaIndex int) schematype.SchemaType { + if schemaIndex < len(schema.StaticFields) { + return schema.StaticFields[schemaIndex] + } + return schema.DynamicFields[schemaIndex-len(schema.StaticFields)] +} diff --git a/packages/services/pkg/protocol-parser/schemaIndexToAbiType_test.go b/packages/services/pkg/protocol-parser/schemaIndexToAbiType_test.go new file mode 100644 index 0000000000..86e02cc8ce --- /dev/null +++ b/packages/services/pkg/protocol-parser/schemaIndexToAbiType_test.go @@ -0,0 +1,39 @@ +package protocolparser_test + +import ( + "testing" + + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + schematype "latticexyz/mud/packages/services/pkg/schema-type" +) + +func TestSchemaIndexToAbiType(t *testing.T) { + schema := protocolparser.Schema{ + StaticFields: []schematype.SchemaType{ + schematype.UINT8, + schematype.UINT16, + schematype.UINT32, + }, + DynamicFields: []schematype.SchemaType{ + schematype.STRING, + schematype.BYTES, + }, + } + tests := []struct { + schemaIndex int + want schematype.SchemaType + }{ + {0, schematype.UINT8}, + {1, schematype.UINT16}, + {2, schematype.UINT32}, + {3, schematype.STRING}, + {4, schematype.BYTES}, + } + + for _, test := range tests { + got := protocolparser.SchemaIndexToAbiType(schema, test.schemaIndex) + if got != test.want { + t.Errorf("SchemaIndexToAbiType(%v, %v) = %v, want %v", schema, test.schemaIndex, got, test.want) + } + } +} diff --git a/packages/services/pkg/protocol-parser/schemaToHex.go b/packages/services/pkg/protocol-parser/schemaToHex.go new file mode 100644 index 0000000000..3a05621aa0 --- /dev/null +++ b/packages/services/pkg/protocol-parser/schemaToHex.go @@ -0,0 +1,27 @@ +package protocolparser + +import ( + "strconv" + "strings" + + godash "github.com/golodash/godash/strings" +) + +func IntToString(number int) string { + return strconv.FormatInt(int64(number), 16) +} + +func SchemaToHex(schema Schema) string { + strs := []string{ + godash.PadStart(IntToString(StaticDataLength(schema.StaticFields)), 4, "0"), + godash.PadStart(IntToString(len(schema.StaticFields)), 2, "0"), + godash.PadStart(IntToString(len(schema.DynamicFields)), 2, "0"), + } + for _, field := range schema.StaticFields { + strs = append(strs, godash.PadStart(IntToString(int(field)), 2, "0")) + } + for _, field := range schema.DynamicFields { + strs = append(strs, godash.PadStart(IntToString(int(field)), 2, "0")) + } + return "0x" + godash.PadEnd(strings.Join(strs, ""), 64, "0") +} diff --git a/packages/services/pkg/protocol-parser/schemaToHex_test.go b/packages/services/pkg/protocol-parser/schemaToHex_test.go new file mode 100644 index 0000000000..6106ff6167 --- /dev/null +++ b/packages/services/pkg/protocol-parser/schemaToHex_test.go @@ -0,0 +1,51 @@ +package protocolparser_test + +import ( + protocolparser "latticexyz/mud/packages/services/pkg/protocol-parser" + . "latticexyz/mud/packages/services/pkg/schema-type" + "testing" +) + +func TestSchemaToHex(t *testing.T) { + schemas := []protocolparser.Schema{ + { + StaticFields: []SchemaType{ + BOOL, + }, + DynamicFields: []SchemaType{}, + }, + { + StaticFields: []SchemaType{ + BOOL, + }, + DynamicFields: []SchemaType{ + BOOL_ARRAY, + }, + }, + { + StaticFields: []SchemaType{ + BYTES32, + INT32, + }, + DynamicFields: []SchemaType{ + UINT256_ARRAY, + ADDRESS_ARRAY, + BYTES, + STRING, + }, + }, + } + + expectedHexes := []string{ + "0x0001010060000000000000000000000000000000000000000000000000000000", + "0x0001010160c20000000000000000000000000000000000000000000000000000", + "0x002402045f2381c3c4c500000000000000000000000000000000000000000000", + } + + for i, schema := range schemas { + hex := protocolparser.SchemaToHex(schema) + if hex != expectedHexes[i] { + t.Errorf("Expected hex to be %s, got %s", expectedHexes[i], hex) + } + } +} diff --git a/packages/services/pkg/protocol-parser/staticDataLength.go b/packages/services/pkg/protocol-parser/staticDataLength.go new file mode 100644 index 0000000000..d5380a13f6 --- /dev/null +++ b/packages/services/pkg/protocol-parser/staticDataLength.go @@ -0,0 +1,11 @@ +package protocolparser + +import schematype "latticexyz/mud/packages/services/pkg/schema-type" + +func StaticDataLength(staticFields []schematype.SchemaType) int { + var length int + for _, field := range staticFields { + length += schematype.StaticAbiTypeToByteLength(field) + } + return length +} diff --git a/packages/services/pkg/protocol-parser/utils.go b/packages/services/pkg/protocol-parser/utils.go new file mode 100644 index 0000000000..fd72367fd8 --- /dev/null +++ b/packages/services/pkg/protocol-parser/utils.go @@ -0,0 +1,39 @@ +package protocolparser + +import ( + schematype "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +func HexSlice(hex string, start int, end int) string { + return "0x" + strings.ReplaceAll(hex, "0x", "")[start*2:end*2] +} + +func HexSliceFrom(hex string, start int) string { + return "0x" + strings.ReplaceAll(hex, "0x", "")[start*2:] +} + +func HexToNumber(hex string) int { + b := hexutil.MustDecode(hex) + i := new(big.Int).SetBytes(b) + return int(i.Int64()) +} + +func BigIntFromString(str string) *big.Int { + b, err := new(big.Int).SetString(str, 10) + if !err { + panic(err) + } + return b +} + +func SchemaTypesToStringTypes(types []schematype.SchemaType) []string { + strs := []string{} + for _, t := range types { + strs = append(strs, strings.ToLower(t.String())) + } + return strs +} diff --git a/packages/services/pkg/protocol-parser/utils_test.go b/packages/services/pkg/protocol-parser/utils_test.go new file mode 100644 index 0000000000..07944c77d5 --- /dev/null +++ b/packages/services/pkg/protocol-parser/utils_test.go @@ -0,0 +1,101 @@ +package protocolparser_test + +import ( + . "latticexyz/mud/packages/services/pkg/protocol-parser" + schematype "latticexyz/mud/packages/services/pkg/schema-type" + "math/big" + "reflect" + "testing" +) + +func TestHexSlice(t *testing.T) { + hexStrings := []string{ + "0x123456", + "0x1234567890", + "0xabcdef1234567890", + } + expectedHexStrings := []string{ + "0x12", + "0x1234", + "0xabcdef", + } + sliceStarts := []int{ + 0, + 0, + 0, + } + sliceEnds := []int{ + 1, + 2, + 3, + } + + for i, hexString := range hexStrings { + slice := HexSlice(hexString, sliceStarts[i], sliceEnds[i]) + if slice != expectedHexStrings[i] { + t.Errorf("Expected slice to be %s, got %s", expectedHexStrings[i], slice) + } + } +} + +func TestHexSliceFrom(t *testing.T) { + hexStrings := []string{ + "0x123456", + "0x1234567890", + } + expectedHexStrings := []string{ + "0x56", + "0x7890", + } + sliceStarts := []int{ + 2, + 3, + } + for i, hexString := range hexStrings { + slice := HexSliceFrom(hexString, sliceStarts[i]) + if slice != expectedHexStrings[i] { + t.Errorf("Expected slice to be %s, got %s", expectedHexStrings[i], slice) + } + } +} + +func TestHexToNumber(t *testing.T) { + hexNumber := "0x123456" + expectedNumber := 1193046 + number := HexToNumber(hexNumber) + if number != expectedNumber { + t.Errorf("Expected number to be %d, got %d", expectedNumber, number) + } +} + +func TestBigIntFromString(t *testing.T) { + bigIntStr := "12345678" + expectedBigInt := big.NewInt(12345678) + bigInt := BigIntFromString(bigIntStr) + if bigInt.Cmp(expectedBigInt) != 0 { + t.Errorf("Expected bigInt to be %d, got %d", expectedBigInt, bigInt) + } +} + +func TestSchemaTypesToStringTypes(t *testing.T) { + schemaTypes := []schematype.SchemaType{ + schematype.UINT8, + schematype.INT16, + schematype.BOOL, + schematype.ADDRESS, + schematype.BYTES32, + } + + expectedStringTypes := []string{ + "uint8", + "int16", + "bool", + "address", + "bytes32", + } + + stringTypes := SchemaTypesToStringTypes(schemaTypes) + if !reflect.DeepEqual(stringTypes, expectedStringTypes) { + t.Errorf("Expected stringTypes to be %v, got %v", expectedStringTypes, stringTypes) + } +} diff --git a/packages/services/pkg/schema-type/arrayAbiTypes.go b/packages/services/pkg/schema-type/arrayAbiTypes.go new file mode 100644 index 0000000000..a42fb60b26 --- /dev/null +++ b/packages/services/pkg/schema-type/arrayAbiTypes.go @@ -0,0 +1,9 @@ +package schematype + +func ArrayAbiTypeToStaticAbiType(schemaType SchemaType) SchemaType { + // Check that the type is actually an array type. + if schemaType < UINT8_ARRAY || schemaType > ADDRESS_ARRAY { + panic("got non-array type: " + schemaType.String()) + } + return (schemaType - UINT8_ARRAY) +} diff --git a/packages/services/pkg/schema-type/schematype_string.go b/packages/services/pkg/schema-type/schematype_string.go new file mode 100644 index 0000000000..f5b59fd866 --- /dev/null +++ b/packages/services/pkg/schema-type/schematype_string.go @@ -0,0 +1,220 @@ +// Code generated by "stringer -type=SchemaType"; DO NOT EDIT. + +package schematype + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[UINT8-0] + _ = x[UINT16-1] + _ = x[UINT24-2] + _ = x[UINT32-3] + _ = x[UINT40-4] + _ = x[UINT48-5] + _ = x[UINT56-6] + _ = x[UINT64-7] + _ = x[UINT72-8] + _ = x[UINT80-9] + _ = x[UINT88-10] + _ = x[UINT96-11] + _ = x[UINT104-12] + _ = x[UINT112-13] + _ = x[UINT120-14] + _ = x[UINT128-15] + _ = x[UINT136-16] + _ = x[UINT144-17] + _ = x[UINT152-18] + _ = x[UINT160-19] + _ = x[UINT168-20] + _ = x[UINT176-21] + _ = x[UINT184-22] + _ = x[UINT192-23] + _ = x[UINT200-24] + _ = x[UINT208-25] + _ = x[UINT216-26] + _ = x[UINT224-27] + _ = x[UINT232-28] + _ = x[UINT240-29] + _ = x[UINT248-30] + _ = x[UINT256-31] + _ = x[INT8-32] + _ = x[INT16-33] + _ = x[INT24-34] + _ = x[INT32-35] + _ = x[INT40-36] + _ = x[INT48-37] + _ = x[INT56-38] + _ = x[INT64-39] + _ = x[INT72-40] + _ = x[INT80-41] + _ = x[INT88-42] + _ = x[INT96-43] + _ = x[INT104-44] + _ = x[INT112-45] + _ = x[INT120-46] + _ = x[INT128-47] + _ = x[INT136-48] + _ = x[INT144-49] + _ = x[INT152-50] + _ = x[INT160-51] + _ = x[INT168-52] + _ = x[INT176-53] + _ = x[INT184-54] + _ = x[INT192-55] + _ = x[INT200-56] + _ = x[INT208-57] + _ = x[INT216-58] + _ = x[INT224-59] + _ = x[INT232-60] + _ = x[INT240-61] + _ = x[INT248-62] + _ = x[INT256-63] + _ = x[BYTES1-64] + _ = x[BYTES2-65] + _ = x[BYTES3-66] + _ = x[BYTES4-67] + _ = x[BYTES5-68] + _ = x[BYTES6-69] + _ = x[BYTES7-70] + _ = x[BYTES8-71] + _ = x[BYTES9-72] + _ = x[BYTES10-73] + _ = x[BYTES11-74] + _ = x[BYTES12-75] + _ = x[BYTES13-76] + _ = x[BYTES14-77] + _ = x[BYTES15-78] + _ = x[BYTES16-79] + _ = x[BYTES17-80] + _ = x[BYTES18-81] + _ = x[BYTES19-82] + _ = x[BYTES20-83] + _ = x[BYTES21-84] + _ = x[BYTES22-85] + _ = x[BYTES23-86] + _ = x[BYTES24-87] + _ = x[BYTES25-88] + _ = x[BYTES26-89] + _ = x[BYTES27-90] + _ = x[BYTES28-91] + _ = x[BYTES29-92] + _ = x[BYTES30-93] + _ = x[BYTES31-94] + _ = x[BYTES32-95] + _ = x[BOOL-96] + _ = x[ADDRESS-97] + _ = x[UINT8_ARRAY-98] + _ = x[UINT16_ARRAY-99] + _ = x[UINT24_ARRAY-100] + _ = x[UINT32_ARRAY-101] + _ = x[UINT40_ARRAY-102] + _ = x[UINT48_ARRAY-103] + _ = x[UINT56_ARRAY-104] + _ = x[UINT64_ARRAY-105] + _ = x[UINT72_ARRAY-106] + _ = x[UINT80_ARRAY-107] + _ = x[UINT88_ARRAY-108] + _ = x[UINT96_ARRAY-109] + _ = x[UINT104_ARRAY-110] + _ = x[UINT112_ARRAY-111] + _ = x[UINT120_ARRAY-112] + _ = x[UINT128_ARRAY-113] + _ = x[UINT136_ARRAY-114] + _ = x[UINT144_ARRAY-115] + _ = x[UINT152_ARRAY-116] + _ = x[UINT160_ARRAY-117] + _ = x[UINT168_ARRAY-118] + _ = x[UINT176_ARRAY-119] + _ = x[UINT184_ARRAY-120] + _ = x[UINT192_ARRAY-121] + _ = x[UINT200_ARRAY-122] + _ = x[UINT208_ARRAY-123] + _ = x[UINT216_ARRAY-124] + _ = x[UINT224_ARRAY-125] + _ = x[UINT232_ARRAY-126] + _ = x[UINT240_ARRAY-127] + _ = x[UINT248_ARRAY-128] + _ = x[UINT256_ARRAY-129] + _ = x[INT8_ARRAY-130] + _ = x[INT16_ARRAY-131] + _ = x[INT24_ARRAY-132] + _ = x[INT32_ARRAY-133] + _ = x[INT40_ARRAY-134] + _ = x[INT48_ARRAY-135] + _ = x[INT56_ARRAY-136] + _ = x[INT64_ARRAY-137] + _ = x[INT72_ARRAY-138] + _ = x[INT80_ARRAY-139] + _ = x[INT88_ARRAY-140] + _ = x[INT96_ARRAY-141] + _ = x[INT104_ARRAY-142] + _ = x[INT112_ARRAY-143] + _ = x[INT120_ARRAY-144] + _ = x[INT128_ARRAY-145] + _ = x[INT136_ARRAY-146] + _ = x[INT144_ARRAY-147] + _ = x[INT152_ARRAY-148] + _ = x[INT160_ARRAY-149] + _ = x[INT168_ARRAY-150] + _ = x[INT176_ARRAY-151] + _ = x[INT184_ARRAY-152] + _ = x[INT192_ARRAY-153] + _ = x[INT200_ARRAY-154] + _ = x[INT208_ARRAY-155] + _ = x[INT216_ARRAY-156] + _ = x[INT224_ARRAY-157] + _ = x[INT232_ARRAY-158] + _ = x[INT240_ARRAY-159] + _ = x[INT248_ARRAY-160] + _ = x[INT256_ARRAY-161] + _ = x[BYTES1_ARRAY-162] + _ = x[BYTES2_ARRAY-163] + _ = x[BYTES3_ARRAY-164] + _ = x[BYTES4_ARRAY-165] + _ = x[BYTES5_ARRAY-166] + _ = x[BYTES6_ARRAY-167] + _ = x[BYTES7_ARRAY-168] + _ = x[BYTES8_ARRAY-169] + _ = x[BYTES9_ARRAY-170] + _ = x[BYTES10_ARRAY-171] + _ = x[BYTES11_ARRAY-172] + _ = x[BYTES12_ARRAY-173] + _ = x[BYTES13_ARRAY-174] + _ = x[BYTES14_ARRAY-175] + _ = x[BYTES15_ARRAY-176] + _ = x[BYTES16_ARRAY-177] + _ = x[BYTES17_ARRAY-178] + _ = x[BYTES18_ARRAY-179] + _ = x[BYTES19_ARRAY-180] + _ = x[BYTES20_ARRAY-181] + _ = x[BYTES21_ARRAY-182] + _ = x[BYTES22_ARRAY-183] + _ = x[BYTES23_ARRAY-184] + _ = x[BYTES24_ARRAY-185] + _ = x[BYTES25_ARRAY-186] + _ = x[BYTES26_ARRAY-187] + _ = x[BYTES27_ARRAY-188] + _ = x[BYTES28_ARRAY-189] + _ = x[BYTES29_ARRAY-190] + _ = x[BYTES30_ARRAY-191] + _ = x[BYTES31_ARRAY-192] + _ = x[BYTES32_ARRAY-193] + _ = x[BOOL_ARRAY-194] + _ = x[ADDRESS_ARRAY-195] + _ = x[BYTES-196] + _ = x[STRING-197] +} + +const _SchemaType_name = "UINT8UINT16UINT24UINT32UINT40UINT48UINT56UINT64UINT72UINT80UINT88UINT96UINT104UINT112UINT120UINT128UINT136UINT144UINT152UINT160UINT168UINT176UINT184UINT192UINT200UINT208UINT216UINT224UINT232UINT240UINT248UINT256INT8INT16INT24INT32INT40INT48INT56INT64INT72INT80INT88INT96INT104INT112INT120INT128INT136INT144INT152INT160INT168INT176INT184INT192INT200INT208INT216INT224INT232INT240INT248INT256BYTES1BYTES2BYTES3BYTES4BYTES5BYTES6BYTES7BYTES8BYTES9BYTES10BYTES11BYTES12BYTES13BYTES14BYTES15BYTES16BYTES17BYTES18BYTES19BYTES20BYTES21BYTES22BYTES23BYTES24BYTES25BYTES26BYTES27BYTES28BYTES29BYTES30BYTES31BYTES32BOOLADDRESSUINT8_ARRAYUINT16_ARRAYUINT24_ARRAYUINT32_ARRAYUINT40_ARRAYUINT48_ARRAYUINT56_ARRAYUINT64_ARRAYUINT72_ARRAYUINT80_ARRAYUINT88_ARRAYUINT96_ARRAYUINT104_ARRAYUINT112_ARRAYUINT120_ARRAYUINT128_ARRAYUINT136_ARRAYUINT144_ARRAYUINT152_ARRAYUINT160_ARRAYUINT168_ARRAYUINT176_ARRAYUINT184_ARRAYUINT192_ARRAYUINT200_ARRAYUINT208_ARRAYUINT216_ARRAYUINT224_ARRAYUINT232_ARRAYUINT240_ARRAYUINT248_ARRAYUINT256_ARRAYINT8_ARRAYINT16_ARRAYINT24_ARRAYINT32_ARRAYINT40_ARRAYINT48_ARRAYINT56_ARRAYINT64_ARRAYINT72_ARRAYINT80_ARRAYINT88_ARRAYINT96_ARRAYINT104_ARRAYINT112_ARRAYINT120_ARRAYINT128_ARRAYINT136_ARRAYINT144_ARRAYINT152_ARRAYINT160_ARRAYINT168_ARRAYINT176_ARRAYINT184_ARRAYINT192_ARRAYINT200_ARRAYINT208_ARRAYINT216_ARRAYINT224_ARRAYINT232_ARRAYINT240_ARRAYINT248_ARRAYINT256_ARRAYBYTES1_ARRAYBYTES2_ARRAYBYTES3_ARRAYBYTES4_ARRAYBYTES5_ARRAYBYTES6_ARRAYBYTES7_ARRAYBYTES8_ARRAYBYTES9_ARRAYBYTES10_ARRAYBYTES11_ARRAYBYTES12_ARRAYBYTES13_ARRAYBYTES14_ARRAYBYTES15_ARRAYBYTES16_ARRAYBYTES17_ARRAYBYTES18_ARRAYBYTES19_ARRAYBYTES20_ARRAYBYTES21_ARRAYBYTES22_ARRAYBYTES23_ARRAYBYTES24_ARRAYBYTES25_ARRAYBYTES26_ARRAYBYTES27_ARRAYBYTES28_ARRAYBYTES29_ARRAYBYTES30_ARRAYBYTES31_ARRAYBYTES32_ARRAYBOOL_ARRAYADDRESS_ARRAYBYTESSTRING" + +var _SchemaType_index = [...]uint16{0, 5, 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 78, 85, 92, 99, 106, 113, 120, 127, 134, 141, 148, 155, 162, 169, 176, 183, 190, 197, 204, 211, 215, 220, 225, 230, 235, 240, 245, 250, 255, 260, 265, 270, 276, 282, 288, 294, 300, 306, 312, 318, 324, 330, 336, 342, 348, 354, 360, 366, 372, 378, 384, 390, 396, 402, 408, 414, 420, 426, 432, 438, 444, 451, 458, 465, 472, 479, 486, 493, 500, 507, 514, 521, 528, 535, 542, 549, 556, 563, 570, 577, 584, 591, 598, 605, 609, 616, 627, 639, 651, 663, 675, 687, 699, 711, 723, 735, 747, 759, 772, 785, 798, 811, 824, 837, 850, 863, 876, 889, 902, 915, 928, 941, 954, 967, 980, 993, 1006, 1019, 1029, 1040, 1051, 1062, 1073, 1084, 1095, 1106, 1117, 1128, 1139, 1150, 1162, 1174, 1186, 1198, 1210, 1222, 1234, 1246, 1258, 1270, 1282, 1294, 1306, 1318, 1330, 1342, 1354, 1366, 1378, 1390, 1402, 1414, 1426, 1438, 1450, 1462, 1474, 1486, 1498, 1511, 1524, 1537, 1550, 1563, 1576, 1589, 1602, 1615, 1628, 1641, 1654, 1667, 1680, 1693, 1706, 1719, 1732, 1745, 1758, 1771, 1784, 1797, 1807, 1820, 1825, 1831} + +func (i SchemaType) String() string { + if i >= SchemaType(len(_SchemaType_index)-1) { + return "SchemaType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _SchemaType_name[_SchemaType_index[i]:_SchemaType_index[i+1]] +} diff --git a/packages/services/pkg/schema-type/staticAbiTypes.go b/packages/services/pkg/schema-type/staticAbiTypes.go new file mode 100644 index 0000000000..c6f38b55a9 --- /dev/null +++ b/packages/services/pkg/schema-type/staticAbiTypes.go @@ -0,0 +1,208 @@ +package schematype + +// StaticAbiTypeToByteLength returns the byte length of a static `SchemaType` type. +func StaticAbiTypeToByteLength(schemaType SchemaType) int { + switch schemaType { + case UINT8: + return 1 + case UINT16: + return 2 + case UINT24: + return 3 + case UINT32: + return 4 + case UINT40: + return 5 + case UINT48: + return 6 + case UINT56: + return 7 + case UINT64: + return 8 + case UINT72: + return 9 + case UINT80: + return 10 + case UINT88: + return 11 + case UINT96: + return 12 + case UINT104: + return 13 + case UINT112: + return 14 + case UINT120: + return 15 + case UINT128: + return 16 + case UINT136: + return 17 + case UINT144: + return 18 + case UINT152: + return 19 + case UINT160: + return 20 + case UINT168: + return 21 + case UINT176: + return 22 + case UINT184: + return 23 + case UINT192: + return 24 + case UINT200: + return 25 + case UINT208: + return 26 + case UINT216: + return 27 + case UINT224: + return 28 + case UINT232: + return 29 + case UINT240: + return 30 + case UINT248: + return 31 + case UINT256: + return 32 + + case INT8: + return 1 + case INT16: + return 2 + case INT24: + return 3 + case INT32: + return 4 + case INT40: + return 5 + case INT48: + return 6 + case INT56: + return 7 + case INT64: + return 8 + case INT72: + return 9 + case INT80: + return 10 + case INT88: + return 11 + case INT96: + return 12 + case INT104: + return 13 + case INT112: + return 14 + case INT120: + return 15 + case INT128: + return 16 + case INT136: + return 17 + case INT144: + return 18 + case INT152: + return 19 + case INT160: + return 20 + case INT168: + return 21 + case INT176: + return 22 + case INT184: + return 23 + case INT192: + return 24 + case INT200: + return 25 + case INT208: + return 26 + case INT216: + return 27 + case INT224: + return 28 + case INT232: + return 29 + case INT240: + return 30 + case INT248: + return 31 + case INT256: + return 32 + + case BYTES1: + return 1 + case BYTES2: + return 2 + case BYTES3: + return 3 + case BYTES4: + return 4 + case BYTES5: + return 5 + case BYTES6: + return 6 + case BYTES7: + return 7 + case BYTES8: + return 8 + case BYTES9: + return 9 + case BYTES10: + return 10 + case BYTES11: + return 11 + case BYTES12: + return 12 + case BYTES13: + return 13 + case BYTES14: + return 14 + case BYTES15: + return 15 + case BYTES16: + return 16 + case BYTES17: + return 17 + case BYTES18: + return 18 + case BYTES19: + return 19 + case BYTES20: + return 20 + case BYTES21: + return 21 + case BYTES22: + return 22 + case BYTES23: + return 23 + case BYTES24: + return 24 + case BYTES25: + return 25 + case BYTES26: + return 26 + case BYTES27: + return 27 + case BYTES28: + return 28 + case BYTES29: + return 29 + case BYTES30: + return 30 + case BYTES31: + return 31 + case BYTES32: + return 32 + + case BOOL: + return 1 + case ADDRESS: + return 20 + default: + return 0 + } +} diff --git a/packages/services/pkg/schema-type/types.go b/packages/services/pkg/schema-type/types.go new file mode 100644 index 0000000000..6ee6422f5d --- /dev/null +++ b/packages/services/pkg/schema-type/types.go @@ -0,0 +1,238 @@ +package schematype + +type SchemaType uint64 + +//nolint:revive,stylecheck // auto-gen + readablity +const ( + UINT8 SchemaType = iota + UINT16 + UINT24 + UINT32 + UINT40 + UINT48 + UINT56 + UINT64 + UINT72 + UINT80 + UINT88 + UINT96 + UINT104 + UINT112 + UINT120 + UINT128 + UINT136 + UINT144 + UINT152 + UINT160 + UINT168 + UINT176 + UINT184 + UINT192 + UINT200 + UINT208 + UINT216 + UINT224 + UINT232 + UINT240 + UINT248 + UINT256 + INT8 + INT16 + INT24 + INT32 + INT40 + INT48 + INT56 + INT64 + INT72 + INT80 + INT88 + INT96 + INT104 + INT112 + INT120 + INT128 + INT136 + INT144 + INT152 + INT160 + INT168 + INT176 + INT184 + INT192 + INT200 + INT208 + INT216 + INT224 + INT232 + INT240 + INT248 + INT256 + BYTES1 + BYTES2 + BYTES3 + BYTES4 + BYTES5 + BYTES6 + BYTES7 + BYTES8 + BYTES9 + BYTES10 + BYTES11 + BYTES12 + BYTES13 + BYTES14 + BYTES15 + BYTES16 + BYTES17 + BYTES18 + BYTES19 + BYTES20 + BYTES21 + BYTES22 + BYTES23 + BYTES24 + BYTES25 + BYTES26 + BYTES27 + BYTES28 + BYTES29 + BYTES30 + BYTES31 + BYTES32 + BOOL + ADDRESS + UINT8_ARRAY + UINT16_ARRAY + UINT24_ARRAY + UINT32_ARRAY + UINT40_ARRAY + UINT48_ARRAY + UINT56_ARRAY + UINT64_ARRAY + UINT72_ARRAY + UINT80_ARRAY + UINT88_ARRAY + UINT96_ARRAY + UINT104_ARRAY + UINT112_ARRAY + UINT120_ARRAY + UINT128_ARRAY + UINT136_ARRAY + UINT144_ARRAY + UINT152_ARRAY + UINT160_ARRAY + UINT168_ARRAY + UINT176_ARRAY + UINT184_ARRAY + UINT192_ARRAY + UINT200_ARRAY + UINT208_ARRAY + UINT216_ARRAY + UINT224_ARRAY + UINT232_ARRAY + UINT240_ARRAY + UINT248_ARRAY + UINT256_ARRAY + INT8_ARRAY + INT16_ARRAY + INT24_ARRAY + INT32_ARRAY + INT40_ARRAY + INT48_ARRAY + INT56_ARRAY + INT64_ARRAY + INT72_ARRAY + INT80_ARRAY + INT88_ARRAY + INT96_ARRAY + INT104_ARRAY + INT112_ARRAY + INT120_ARRAY + INT128_ARRAY + INT136_ARRAY + INT144_ARRAY + INT152_ARRAY + INT160_ARRAY + INT168_ARRAY + INT176_ARRAY + INT184_ARRAY + INT192_ARRAY + INT200_ARRAY + INT208_ARRAY + INT216_ARRAY + INT224_ARRAY + INT232_ARRAY + INT240_ARRAY + INT248_ARRAY + INT256_ARRAY + BYTES1_ARRAY + BYTES2_ARRAY + BYTES3_ARRAY + BYTES4_ARRAY + BYTES5_ARRAY + BYTES6_ARRAY + BYTES7_ARRAY + BYTES8_ARRAY + BYTES9_ARRAY + BYTES10_ARRAY + BYTES11_ARRAY + BYTES12_ARRAY + BYTES13_ARRAY + BYTES14_ARRAY + BYTES15_ARRAY + BYTES16_ARRAY + BYTES17_ARRAY + BYTES18_ARRAY + BYTES19_ARRAY + BYTES20_ARRAY + BYTES21_ARRAY + BYTES22_ARRAY + BYTES23_ARRAY + BYTES24_ARRAY + BYTES25_ARRAY + BYTES26_ARRAY + BYTES27_ARRAY + BYTES28_ARRAY + BYTES29_ARRAY + BYTES30_ARRAY + BYTES31_ARRAY + BYTES32_ARRAY + BOOL_ARRAY + ADDRESS_ARRAY + BYTES + STRING +) + +func (s SchemaType) IsDynamic() bool { + // Every dynamic type is greater than ADDRESS + return int(s) > int(ADDRESS) +} + +func (s SchemaType) IsArray() bool { + return int(s) >= int(UINT8_ARRAY) && int(s) <= int(ADDRESS_ARRAY) +} + +func (s SchemaType) ByteLength() int { + //nolint:gocritic // no switch + if s < 32 { + // uint8-256 + return int(s) + 1 + } else if s < 64 { + // int8-256, offset by 32 + return int(s) + 1 - 32 + } else if s < 96 { + // bytes1-32, offset by 64 + return int(s) + 1 - 64 + } + + // Other static types + if s == BOOL { + return 1 + } else if s == ADDRESS { + return 20 + } + + // Return 0 for all dynamic types + return 0 +} From 70e4d8eb41d086befbd38db6df1628e573c9f7f9 Mon Sep 17 00:00:00 2001 From: alvarius Date: Thu, 27 Jul 2023 19:05:38 +0100 Subject: [PATCH 2/9] chore: fix snapshot release action (#1203) --- .github/workflows/snapshot.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 587d7a11e7..4837cd0d09 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -28,6 +28,10 @@ jobs: env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + # Remove this once https://github.com/changesets/changesets/issues/1195 is addressed + - name: Temporarily exit pre-release mode to release a snapshot + run: pnpm changeset pre exit + - name: Clean shell: bash run: pnpm turbo run clean --force --concurrency 10 @@ -44,4 +48,3 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - From e259ef79f4d9026353176d0f74628cae50c2f69b Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 28 Jul 2023 02:51:15 -0700 Subject: [PATCH 3/9] fix(cli): explicit import of world as type (#1206) Co-authored-by: pwrstudio --- .changeset/mean-pans-study.md | 6 ++++++ .prettierignore | 3 ++- e2e/packages/client-vanilla/src/mud/contractComponents.ts | 6 +++++- .../packages/client-phaser/src/mud/contractComponents.ts | 6 +++++- .../packages/client-react/src/mud/contractComponents.ts | 6 +++++- .../packages/client-vanilla/src/mud/contractComponents.ts | 6 +++++- packages/cli/src/render-ts/renderRecsV1Tables.ts | 2 +- .../src/mud-definitions/store/contractComponents.ts | 6 +++++- .../src/mud-definitions/world/contractComponents.ts | 6 +++++- .../phaser/packages/client/src/mud/contractComponents.ts | 6 +++++- .../react/packages/client/src/mud/contractComponents.ts | 6 +++++- .../threejs/packages/client/src/mud/contractComponents.ts | 6 +++++- .../vanilla/packages/client/src/mud/contractComponents.ts | 6 +++++- 13 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 .changeset/mean-pans-study.md diff --git a/.changeset/mean-pans-study.md b/.changeset/mean-pans-study.md new file mode 100644 index 0000000000..96f3a51a21 --- /dev/null +++ b/.changeset/mean-pans-study.md @@ -0,0 +1,6 @@ +--- +"@latticexyz/cli": patch +"@latticexyz/std-client": patch +--- + +Generated `contractComponents` now properly import `World` as type diff --git a/.prettierignore b/.prettierignore index 50f1dc1280..cb96b10c21 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ dist **/types/ethers-contracts **/.next -templates/phaser/packages/art \ No newline at end of file +templates/phaser/packages/art +**/contractComponents.ts diff --git a/e2e/packages/client-vanilla/src/mud/contractComponents.ts b/e2e/packages/client-vanilla/src/mud/contractComponents.ts index 9ffa13a377..4c59ed6f18 100644 --- a/e2e/packages/client-vanilla/src/mud/contractComponents.ts +++ b/e2e/packages/client-vanilla/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts b/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts index 5ab7b05983..e9ccad3633 100644 --- a/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts +++ b/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/examples/minimal/packages/client-react/src/mud/contractComponents.ts b/examples/minimal/packages/client-react/src/mud/contractComponents.ts index 5ab7b05983..e9ccad3633 100644 --- a/examples/minimal/packages/client-react/src/mud/contractComponents.ts +++ b/examples/minimal/packages/client-react/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts b/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts index 5ab7b05983..e9ccad3633 100644 --- a/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts +++ b/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/packages/cli/src/render-ts/renderRecsV1Tables.ts b/packages/cli/src/render-ts/renderRecsV1Tables.ts index e3b53d0609..39c015e853 100644 --- a/packages/cli/src/render-ts/renderRecsV1Tables.ts +++ b/packages/cli/src/render-ts/renderRecsV1Tables.ts @@ -6,7 +6,7 @@ export function renderRecsV1Tables(options: RecsV1TableOptions) { return `/* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { defineComponent, Type as RecsType, type World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/packages/std-client/src/mud-definitions/store/contractComponents.ts b/packages/std-client/src/mud-definitions/store/contractComponents.ts index 30372c5ff5..76d47f99bc 100644 --- a/packages/std-client/src/mud-definitions/store/contractComponents.ts +++ b/packages/std-client/src/mud-definitions/store/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/packages/std-client/src/mud-definitions/world/contractComponents.ts b/packages/std-client/src/mud-definitions/world/contractComponents.ts index f697d8a359..09bde1b123 100644 --- a/packages/std-client/src/mud-definitions/world/contractComponents.ts +++ b/packages/std-client/src/mud-definitions/world/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/templates/phaser/packages/client/src/mud/contractComponents.ts b/templates/phaser/packages/client/src/mud/contractComponents.ts index 943b86184e..4b8147ca25 100644 --- a/templates/phaser/packages/client/src/mud/contractComponents.ts +++ b/templates/phaser/packages/client/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/templates/react/packages/client/src/mud/contractComponents.ts b/templates/react/packages/client/src/mud/contractComponents.ts index 943b86184e..4b8147ca25 100644 --- a/templates/react/packages/client/src/mud/contractComponents.ts +++ b/templates/react/packages/client/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/templates/threejs/packages/client/src/mud/contractComponents.ts b/templates/threejs/packages/client/src/mud/contractComponents.ts index 40e0720d05..4aa48fd895 100644 --- a/templates/threejs/packages/client/src/mud/contractComponents.ts +++ b/templates/threejs/packages/client/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { diff --git a/templates/vanilla/packages/client/src/mud/contractComponents.ts b/templates/vanilla/packages/client/src/mud/contractComponents.ts index 943b86184e..4b8147ca25 100644 --- a/templates/vanilla/packages/client/src/mud/contractComponents.ts +++ b/templates/vanilla/packages/client/src/mud/contractComponents.ts @@ -1,6 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; +import { + defineComponent, + Type as RecsType, + type World, +} from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { From 5e9eb5a707a3445b890558c66fb06591d4c7893d Mon Sep 17 00:00:00 2001 From: kooshaza Date: Fri, 28 Jul 2023 11:13:15 +0100 Subject: [PATCH 4/9] docs: add a 'view roadmap' button to callout (#1191) --- docs/components/Logo.tsx | 6 +++++- docs/components/WarningBox.tsx | 9 ++++---- docs/pages/_meta.js | 6 ++++++ docs/pages/index.mdx | 36 +++++++++++++++++++++----------- docs/public/mud-cover-photo.png | Bin 0 -> 8174 bytes 5 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 docs/public/mud-cover-photo.png diff --git a/docs/components/Logo.tsx b/docs/components/Logo.tsx index d29ecf52b1..e2fec91e7a 100644 --- a/docs/components/Logo.tsx +++ b/docs/components/Logo.tsx @@ -5,8 +5,12 @@ export default function Logo() { const [src, setSrc] = useState("/logo512-white.png"); // default to the dark theme logo const { theme } = useTheme(); + // useEffect(() => { + // setSrc(theme === "light" ? "/logo512-black.png" : "/logo512-white.png"); + //}, [theme]); + useEffect(() => { - setSrc(theme === "light" ? "/logo512-black.png" : "/logo512-white.png"); + setSrc(theme === "light" ? "/mud-cover-photo.png" : "/mud-cover-photo.png"); }, [theme]); return MUD logo; diff --git a/docs/components/WarningBox.tsx b/docs/components/WarningBox.tsx index 8f4b279ac2..bbb2f787f4 100644 --- a/docs/components/WarningBox.tsx +++ b/docs/components/WarningBox.tsx @@ -3,12 +3,12 @@ import React from "react"; const WarningBox = ({ title, message }) => { const styles = { container: { - backgroundColor: "#ffebee", + backgroundColor: "#FDF2F3", borderRadius: "4px", - boxShadow: "0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12)", + border: "1px solid #E8D9DA", padding: "12px 20px", margin: "16px 0", - color: "#b71c1c", + color: "#7D221C", }, header: { display: "flex", @@ -16,7 +16,6 @@ const WarningBox = ({ title, message }) => { fontSize: "1rem", fontWeight: "bold", lineHeight: "1.43", - letterSpacing: "0.01071em", }, icon: { marginRight: "12px", @@ -26,8 +25,8 @@ const WarningBox = ({ title, message }) => { fontSize: "1rem", fontWeight: "400", lineHeight: "1.43", - letterSpacing: "0.01071em", paddingLeft: "34px", + color: "#995A56", }, }; diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js index 4547f8b6b7..86bc3af5a6 100644 --- a/docs/pages/_meta.js +++ b/docs/pages/_meta.js @@ -11,6 +11,12 @@ export default { plugins: "Plugins", tutorials: "Tutorials", contribute: "Contribute", + roadmap: { + title: "Roadmap", + type: "page", + href: "https://roadmap.mud.dev", + newWindow: true, + }, community: { title: "Community", type: "page", diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index df2259c1fc..053dfafb94 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -7,27 +7,34 @@ import Logo from "../components/Logo"; <>

Please note that MUD v2 is still under development and some APIs may change! Stay up to date with MUD core - development, changes, and roadmap by checking out the{" "} - + development, changes, and  + + roadmap + by checking out the Github repo - {" "} - and join the{" "} - - MUD Discord + and join the + MUD Discord. {" "}

+
} />
-
+
-# MUD - -## Introduction +# MUD Introduction MUD is a framework for ambitious Ethereum applications. It compresses the complexity of building EVM apps with a tightly integrated software stack. @@ -45,9 +52,14 @@ MUD is maximally onchain: the entire application state lives in the EVM, and the ## Community support -[Join our Discord](https://lattice.xyz/discord) to get support and connect with the community! +Check out the following resources to learn more and get support: -Check out our [community wiki](https://community.mud.dev) for MUD projects and MUD-related articles, videos, and podcasts. +- [Discord](https://lattice.xyz/discord): get support and connect with the community! +- [New releases](https://github.com/latticexyz/mud/releases): see recent changes to MUD. +- [Roadmap](https://roadmap.mud.dev): a high-level overview of what we'll be working on next. +- [Status](https://status.mud.dev): take a look at ongoing and upcoming initatives. +- [Contribute](https://contribute.mud.dev): start contributing with some good first tasks. +- [Community wiki](https://community.mud.dev): for MUD projects and MUD-related articles, videos, and podcasts. ## License diff --git a/docs/public/mud-cover-photo.png b/docs/public/mud-cover-photo.png new file mode 100644 index 0000000000000000000000000000000000000000..a69e7713684f14eb9270074adf6be9e41ae6cbc3 GIT binary patch literal 8174 zcmeHM2~?9=mi{TXs!~K`l`RM=VQ~eNJ*Wf_R4OP-g;h|Y*g<5M;Mgh&kf1`LKtMxB zM2wLFMAq2KQnH$YuoE;0B1=Mqu#?RDai(YLRG*&eGnUimOuuvTzx?mL{QrI5z4yEK zzTm$*X(j%x!nY6vi667Ju!o@a;OkdgzJ@!iNa_&iz6r7Z{sIKa?u0*L$Lx1ZfkCkg z_Etxr$E`{qz|C5p!zT_yP!Vb4@|krIgt&6d;_&GxvB?4P)IVP&ck?~$<|Za4n)c}~ z)r`ORDD*N|({1J}J zzNj54&Z^llcdH(kiOF3)cc!PT=S~l~j9eCftj$6z=GB>~h~svmk?CzY+-(&Viyyf8 zWjR7zWiC!rNFaB)#ye>G9kNi5&{KN~L<8-KLAsYyfn;SPc~}C+eaz!6^(4h}?khV9 zIxRJVg3>s-YggC3cC?|+-}?Bl2dpBxHM|$)7~fG`rW5V@+cPMsh zLnjc+8Sl*&f~OFxGrg`C9x)EGqo@1n)GT)R!qc&U$@0}1C=8iS=RRoZ4BEVUuS&8E zw6e;3_Zqc&n|e%>b8T~ja07go;Hn_mXY|$TgtgUb2PORJlX#G|^}hySjQ)kkC;Rw~ zIXu`3LC+~=p(jjR2e2uQ3b{IUIq$Xi?{@&+?#Y(|zq%{#8iLi2pG>*Mv}sd9HYBY% zCkBRl{{%lV@NQm5qD{FZ?KIa{uS*>ueeldDll@Yrx4MC*u>h`qWE$m3j5@_}$>Y84 zK>tv8^iAH85tSxCQy^9DQ6OwW29wp380lszGaj2nGC&w$iNR(aGI>%O7|ELka~*zF z!@+h9ujXfm-1zhD>_&i0n>T$M1i4#M%NyeA?_;w|sS4=b9-Y2>n${-VcNj={Hvg!{ zU>ho?W-BRHdkqAkG7Mo@AV_sP3=(Kt0l?6ka~&rRZiJu`&Hp|MCVsu_e>?CHc>UBy z)&MK9{a^>h2dz%PcDaxo$GHT9(rA=pgd78r)mb8p2OG2B4qo-c3U}kVOS(t;UsoY?S;zpi6Idk5{Tf`SHg=Xi+An&w5K;E1Skk4dOtb<3rM^%C zbD*WBe(IrbzWMa!4<2v;d^hjUQlNH6K2s_#^}HdkATZno#&E0qYPx*~KfgRM0MLFN z6c-N1ssGRf=sz#!uzEk&L+{yuCuz{~^3=7+O_}ehZ_@qs)Xv|}&wQT(CSB?7KFL!4QC)RbIQI00bjWTjI2NBCjSalI>2#VNauoF{W+%~l0#uE zMTRILUhfpNa{6>(F{XAgC2NSr6K=p1gs-=4Z^g}2?%!`FOWU{KOaT|uhfC%c-GDWr z1~%|SwKK4HYlcVki5a>Jf;QE?W)L47Kl${wykd&lNz_tR)U!1_U%h`<}6#{cMPg z>9{gjW6WKt@A4WQz2SS+)037|EmcGT}sU<1uhaShp{7GLT@W>_= zL-|SHmHWH-eTZjfEVbO2Fm@=*xJ{WJ5~UtRq-`~mxZu5ZUU^8j@O zw=>u7-ZRU*{gGSi$jukUK)NLfM7e#)#9#{vHAVJK7hY84-0WHjGndrZRX>DpP$4kA zUt&5s-r>Pxjss;wBjQRXTRdt6x0qV*86);$2`}octT;KSYSURWfrYgG#Uo&msvOv3 zLUgHLDRs?V-S&1dbc?dk=X^|~su?hU=?&knmOP)&{AI7^)YL%Od@NZUg2LcE!9uL& zLz(A&&I3?XrB+b~AsMEFq!$%{@*Zv6ldJ|ver9I2UVX3e?As#2 zj*XNq2F_X6n7Z_$NB+?zFPfXf zP57e{UVdQ*2)E@CBoV*+XiFFK29n}PukQ@>u@vKj?6nA&!`2_i{2 zJ*a5{*)CNMqXs1X4+Rh%<&_MSL?gL1ht_XaPIPo;SF5o_H(WUVNqg{W*D}XNxu_L< z)My(I1R+_8zt2IwS{Y3Mu~eXU2s)t*n^kHu{2jEv9mK%IKazpL=~NhZNYYPGp8Pa+N&o~5@YwzNWH&kD6L4>z!g^s8%RF}1WE9~1lsg@tfzLTCHB^KS44 z5J%Ts2RX328hE?;DPCqN|0yH(R7qjJ@FTyw-StO5$hoIo%BgxGFtii+wsGc0sH=L2 zXMtIBeRKTbP{upl4=jc*e!y zS)^0%1-bIzfyMds@y8@SpNaIE=?*ao;kg}-#SUDsag86=53Mhkvydc{$;`oikf;5O z25(ipnx8xWcG$AoZ*qyB^>Om4m(#B+E57;5TE(w z*+})Oy_Hp(_VCCrnQm2yxS_%Xr4BnXnu@<2TE^;G)+L&41a zFaY7shY!A2Uv8Lf$U&IN7VFZ=FP&_C$jYx(WG@nZ(+i}e_*0P#$ zBQ@k*w8TWf@lQl*idkIb$kF_xBLjLOV#4XpGPHfVrZO7HVFpmliel04DRyFhQ)T6len$14&fwmy z=rrR-{&F#jc=_c9N+O=gls5`P0=sstGF}Tg@5qTAdu321T0m0rT!~$7m)w9Fu0gNW z058?zL}POAH+)Qb5WYtWLIzxH)8t<(t5JW*@{`^VbmX!8uEA@tJ(iMKj(?(Imkqo{ zR*tt>43fovC@5HR zRlg(@?8bCRaF-mFV%{z+Tt3^|Huc6lZX^#UkJeWZJkT$DN%aeO7u6ryN5g2zEZr1j z3KTgjxEYP2h@lZAXY}3`J|bu#FKXn~0LCJ3;S_!MzJc6|6i(CcQRsgOn~o7I;MSO22U%V42&@pGy8j;s zpKuW}C6!{SPVm#i8QD;g`WcRfcLW}ruoXgq^G9s?Wb43e|FlP(;)Ay8uf?D@KEO|* zW<|s{yoO4w0YSky-lSEiDAzF4akk{e6jMF)-E$$RPng897J=EF2GLn%(-|+Fi#~24 zXTo>$h>oM~71FySCF~R_!uFlMjz8rxL26P zzppr`+*IkJo3JQ1$Cepf9t&(a{F?9U1fO#_7PPe17v0M%N?Q>&pcGg9I{{Y{l}LNz zK6>vD3osz~>aF=@^yi}6-IE`9B+3X^)IDn5;a>{K=&^-eaBz596I07u zT^*xUIx_oiDk922ATFA`nzjQ~mM#Eg;Yo$@ih7<1#?w2r+2A3ZqDY12pQQQKJ zA^aFXGxea~;x7Fis(Eq`)0S*NrzdS6~-5)*^ zqBkaZldh;>u$ASf4-Ee5sowIHpWr0J_Q+snX^}i@JVjp7u+v2DJ0R)3`SoB%XM4l7 z^+052g=Sz)aQmJ43t0I(ii!f4BHKYDOYpYbTV2L<}E&xb$RT1h1d_qOJGjS1?T z5US(Schdpz|1O|S7M|{PD4;FB?xzoz-*Q{pY*#&7BJe1POslvA|1}3%?=KBmS40e9 z`4SIhHfQyL?jF Date: Fri, 28 Jul 2023 11:18:26 +0100 Subject: [PATCH 5/9] docs: moar margin above cover photo (#1207) --- docs/pages/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 053dfafb94..bcb2a915f2 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -29,7 +29,7 @@ import Logo from "../components/Logo"; } />
-
+
From c963b46c7eaceebc652930936643365b8c48a021 Mon Sep 17 00:00:00 2001 From: dk1a Date: Fri, 28 Jul 2023 17:28:24 +0300 Subject: [PATCH 6/9] refactor(store): optimize Storage library (#1194) --- .changeset/brave-rings-tickle.md | 5 + packages/store/gas-report.json | 236 +++++++++++++---------- packages/store/src/Storage.sol | 201 ++++++++++--------- packages/store/src/StoreCore.sol | 4 +- packages/store/test/Gas.t.sol | 38 +--- packages/store/test/GasStorageLoad.t.sol | 99 ++++++++++ packages/store/test/Storage.t.sol | 4 +- packages/world/gas-report.json | 104 +++++----- 8 files changed, 398 insertions(+), 293 deletions(-) create mode 100644 .changeset/brave-rings-tickle.md create mode 100644 packages/store/test/GasStorageLoad.t.sol diff --git a/.changeset/brave-rings-tickle.md b/.changeset/brave-rings-tickle.md new file mode 100644 index 0000000000..bd9baaf30d --- /dev/null +++ b/.changeset/brave-rings-tickle.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store": patch +--- + +Optimize storage library diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 1835e25afd..4f8c9d2578 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -87,121 +87,157 @@ "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "pass abi encoded bytes to external contract", - "gasUsed": 6563 + "gasUsed": 6551 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "pass custom encoded bytes to external contract", - "gasUsed": 1457 + "gasUsed": 1445 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", + "test": "testCompareStorageWriteMUD", "name": "MUD storage write (cold, 1 word)", - "gasUsed": 22469 + "gasUsed": 22339 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", + "test": "testCompareStorageWriteMUD", "name": "MUD storage write (cold, 1 word, partial)", - "gasUsed": 22432 + "gasUsed": 22406 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", + "test": "testCompareStorageWriteMUD", "name": "MUD storage write (cold, 10 words)", - "gasUsed": 200429 + "gasUsed": 199795 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", + "test": "testCompareStorageWriteMUD", "name": "MUD storage write (warm, 1 word)", - "gasUsed": 469 + "gasUsed": 339 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", + "test": "testCompareStorageWriteMUD", "name": "MUD storage write (warm, 1 word, partial)", - "gasUsed": 532 + "gasUsed": 506 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", + "test": "testCompareStorageWriteMUD", "name": "MUD storage write (warm, 10 words)", - "gasUsed": 2429 + "gasUsed": 1795 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", - "name": "MUD storage load (warm, 1 word)", - "gasUsed": 630 - }, - { - "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", - "name": "MUD storage load (warm, 1 word, partial)", - "gasUsed": 577 - }, - { - "file": "test/Gas.t.sol", - "test": "testCompareStorageMUD", - "name": "MUD storage load (warm, 10 words)", - "gasUsed": 2655 - }, - { - "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "test": "testCompareStorageWriteSolidity", "name": "solidity storage write (cold, 1 word)", "gasUsed": 22107 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "test": "testCompareStorageWriteSolidity", "name": "solidity storage write (cold, 1 word, partial)", "gasUsed": 22136 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "test": "testCompareStorageWriteSolidity", "name": "solidity storage write (cold, 10 words)", "gasUsed": 199902 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "test": "testCompareStorageWriteSolidity", "name": "solidity storage write (warm, 1 word)", "gasUsed": 107 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "test": "testCompareStorageWriteSolidity", "name": "solidity storage write (warm, 1 word, partial)", "gasUsed": 236 }, { "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "test": "testCompareStorageWriteSolidity", "name": "solidity storage write (warm, 10 words)", "gasUsed": 1988 }, { - "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load (cold, 1 word)", + "gasUsed": 2411 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load (cold, 1 word, partial)", + "gasUsed": 2460 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load (cold, 10 words)", + "gasUsed": 19911 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load (warm, 1 word)", + "gasUsed": 412 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load (warm, 1 word, partial)", + "gasUsed": 460 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load (warm, 10 words)", + "gasUsed": 1914 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadSolidity", + "name": "solidity storage load (cold, 1 word)", + "gasUsed": 2109 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadSolidity", + "name": "solidity storage load (cold, 1 word, partial)", + "gasUsed": 2126 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadSolidity", + "name": "solidity storage load (cold, 10 words)", + "gasUsed": 19894 + }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadSolidity", "name": "solidity storage load (warm, 1 word)", "gasUsed": 109 }, { - "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadSolidity", "name": "solidity storage load (warm, 1 word, partial)", "gasUsed": 126 }, { - "file": "test/Gas.t.sol", - "test": "testCompareStorageSolidity", + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadSolidity", "name": "solidity storage load (warm, 10 words)", - "gasUsed": 1916 + "gasUsed": 1897 }, { "file": "test/KeyEncoding.t.sol", @@ -225,13 +261,13 @@ "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 111108 + "gasUsed": 110779 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 12600 + "gasUsed": 12438 }, { "file": "test/PackedCounter.t.sol", @@ -381,43 +417,43 @@ "file": "test/Storage.t.sol", "test": "testStoreLoad", "name": "store 1 storage slot", - "gasUsed": 22503 + "gasUsed": 22339 }, { "file": "test/Storage.t.sol", "test": "testStoreLoad", "name": "store 34 bytes over 3 storage slots (with offset and safeTrail))", - "gasUsed": 23158 + "gasUsed": 23009 }, { "file": "test/Storage.t.sol", "test": "testStoreLoad", "name": "load 34 bytes over 3 storage slots (with offset and safeTrail))", - "gasUsed": 1099 + "gasUsed": 865 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (cold, 1 slot)", - "gasUsed": 8152 + "gasUsed": 7996 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 1 slot)", - "gasUsed": 2180 + "gasUsed": 2065 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (semi-cold, 1 slot)", - "gasUsed": 4185 + "gasUsed": 4070 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 2 slots)", - "gasUsed": 4471 + "gasUsed": 4296 }, { "file": "test/StoreCoreDynamic.t.sol", @@ -447,43 +483,43 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 30792 + "gasUsed": 30424 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 18847 + "gasUsed": 18479 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 32675 + "gasUsed": 32244 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 18730 + "gasUsed": 18299 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 7321 + "gasUsed": 7267 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 2914 + "gasUsed": 2758 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 3587 + "gasUsed": 3420 }, { "file": "test/StoreCoreGas.t.sol", @@ -495,13 +531,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access slice of dynamic field of non-existing record", - "gasUsed": 1324 + "gasUsed": 1202 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 10447 + "gasUsed": 10213 }, { "file": "test/StoreCoreGas.t.sol", @@ -519,61 +555,61 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 66466 + "gasUsed": 66065 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 74409 + "gasUsed": 73933 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 30350 + "gasUsed": 29860 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 23011 + "gasUsed": 22510 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 66466 + "gasUsed": 66065 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 167846 + "gasUsed": 167262 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 33500 + "gasUsed": 32942 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 24483 + "gasUsed": 23977 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 16518 + "gasUsed": 16124 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 39234 + "gasUsed": 38780 }, { "file": "test/StoreCoreGas.t.sol", @@ -597,13 +633,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 109160 + "gasUsed": 108831 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "get complex record with dynamic data (4 slots)", - "gasUsed": 6442 + "gasUsed": 6280 }, { "file": "test/StoreCoreGas.t.sol", @@ -639,103 +675,103 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 39378 + "gasUsed": 39144 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (1 slot)", - "gasUsed": 2915 + "gasUsed": 2759 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 34340 + "gasUsed": 34091 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (overlap 2 slot)", - "gasUsed": 3755 + "gasUsed": 3580 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 56839 + "gasUsed": 56571 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, first dynamic field)", - "gasUsed": 3811 + "gasUsed": 3610 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 34971 + "gasUsed": 34704 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 3826 + "gasUsed": 3625 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 38827 + "gasUsed": 38606 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "get static record (1 slot)", - "gasUsed": 1320 + "gasUsed": 1266 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 61395 + "gasUsed": 61111 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "get static record (2 slots)", - "gasUsed": 1569 + "gasUsed": 1455 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetMetadata", "name": "StoreCore: set table metadata", - "gasUsed": 252784 + "gasUsed": 251951 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 16064 + "gasUsed": 15670 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 17155 + "gasUsed": 16641 }, { "file": "test/StoreMetadata.t.sol", "test": "testSetAndGet", "name": "set record in StoreMetadataTable", - "gasUsed": 251257 + "gasUsed": 250424 }, { "file": "test/StoreMetadata.t.sol", "test": "testSetAndGet", "name": "get record from StoreMetadataTable", - "gasUsed": 12018 + "gasUsed": 11430 }, { "file": "test/StoreSwitch.t.sol", @@ -753,37 +789,37 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "set field in Callbacks", - "gasUsed": 62243 + "gasUsed": 61975 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "get field from Callbacks (warm)", - "gasUsed": 5305 + "gasUsed": 5104 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "push field to Callbacks", - "gasUsed": 39931 + "gasUsed": 39481 }, { "file": "test/tables/Hooks.t.sol", "test": "testSetAndGet", "name": "set field in Hooks", - "gasUsed": 64400 + "gasUsed": 64132 }, { "file": "test/tables/Hooks.t.sol", "test": "testSetAndGet", "name": "get field from Hooks (warm)", - "gasUsed": 5455 + "gasUsed": 5254 }, { "file": "test/tables/Hooks.t.sol", "test": "testSetAndGet", "name": "push field to Hooks", - "gasUsed": 39922 + "gasUsed": 39472 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -849,12 +885,12 @@ "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 37646 + "gasUsed": 37425 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "get Vector2 record", - "gasUsed": 4457 + "gasUsed": 4403 } ] diff --git a/packages/store/src/Storage.sol b/packages/store/src/Storage.sol index 403de0490a..0961cf4d20 100644 --- a/packages/store/src/Storage.sol +++ b/packages/store/src/Storage.sol @@ -2,16 +2,9 @@ pragma solidity >=0.8.0; import { leftMask } from "./Utils.sol"; +import { Memory } from "./Memory.sol"; -/** - * TODO Probably not fully optimized - * (see https://github.com/latticexyz/mud/issues/444) - */ library Storage { - function store(uint256 storagePointer, bytes memory data) internal { - store(storagePointer, 0, data); - } - function store(uint256 storagePointer, bytes32 data) internal { assembly { sstore(storagePointer, data) @@ -19,59 +12,59 @@ library Storage { } function store(uint256 storagePointer, uint256 offset, bytes memory data) internal { - uint256 memoryPointer; - assembly { - memoryPointer := add(data, 0x20) - } - store(storagePointer, offset, memoryPointer, data.length); + store(storagePointer, offset, Memory.dataPointer(data), data.length); } /** - * @notice Stores raw bytes to storage at the given storagePointer and offset (keeping the rest of the word intact) + * Stores raw bytes to storage at the given storagePointer and offset (keeping the rest of the word intact) */ function store(uint256 storagePointer, uint256 offset, uint256 memoryPointer, uint256 length) internal { - // Support offsets that are greater than 32 bytes by incrementing the storagePointer and decrementing the offset - unchecked { - storagePointer += offset / 32; - offset %= 32; - } - - // For the first word, if there is an offset, apply a mask to beginning if (offset > 0) { - // Get the word's remaining length after the offset - uint256 wordRemainder; - // (safe because of `offset %= 32` at the start) - unchecked { - wordRemainder = 32 - offset; + // Support offsets that are greater than 32 bytes by incrementing the storagePointer and decrementing the offset + if (offset >= 32) { + unchecked { + storagePointer += offset / 32; + offset %= 32; + } } - uint256 mask = leftMask(length); - /// @solidity memory-safe-assembly - assembly { - // Load data from memory and offset it to match storage - let bitOffset := mul(offset, 8) - mask := shr(bitOffset, mask) - let offsetData := shr(bitOffset, mload(memoryPointer)) - - sstore( - storagePointer, - or( - // Store the middle part - and(offsetData, mask), - // Preserve the surrounding parts - and(sload(storagePointer), not(mask)) + // For the first word, if there is an offset, apply a mask to beginning + if (offset > 0) { + // Get the word's remaining length after the offset + uint256 wordRemainder; + // (safe because of `offset %= 32` at the start) + unchecked { + wordRemainder = 32 - offset; + } + + uint256 mask = leftMask(length); + /// @solidity memory-safe-assembly + assembly { + // Load data from memory and offset it to match storage + let bitOffset := mul(offset, 8) + mask := shr(bitOffset, mask) + let offsetData := shr(bitOffset, mload(memoryPointer)) + + sstore( + storagePointer, + or( + // Store the middle part + and(offsetData, mask), + // Preserve the surrounding parts + and(sload(storagePointer), not(mask)) + ) ) - ) - } - // Return if done - if (length <= wordRemainder) return; - - // Advance pointers - storagePointer += 1; - // (safe because of `length <= prefixLength` earlier) - unchecked { - memoryPointer += wordRemainder; - length -= wordRemainder; + } + // Return if done + if (length <= wordRemainder) return; + + // Advance pointers + // (safe because of `length <= wordRemainder` earlier) + unchecked { + storagePointer += 1; + memoryPointer += wordRemainder; + length -= wordRemainder; + } } } @@ -81,9 +74,8 @@ library Storage { assembly { sstore(storagePointer, mload(memoryPointer)) } - storagePointer += 1; - // (safe unless length is improbably large) unchecked { + storagePointer += 1; memoryPointer += 32; length -= 32; } @@ -113,69 +105,77 @@ library Storage { } } - function load(uint256 storagePointer, uint256 length) internal view returns (bytes memory) { - return load(storagePointer, length, 0); - } - /** - * @notice Load raw bytes from storage at the given storagePointer, offset, and length + * Load raw bytes from storage at the given storagePointer, offset, and length */ function load(uint256 storagePointer, uint256 length, uint256 offset) internal view returns (bytes memory result) { - // TODO this will probably use less gas via manual memory allocation - // (see https://github.com/latticexyz/mud/issues/444) - result = new bytes(length); uint256 memoryPointer; + /// @solidity memory-safe-assembly assembly { + // Solidity's YulUtilFunctions::roundUpFunction + function round_up_to_mul_of_32(value) -> _result { + _result := and(add(value, 31), not(31)) + } + + // Allocate memory + result := mload(0x40) memoryPointer := add(result, 0x20) + mstore(0x40, round_up_to_mul_of_32(add(memoryPointer, length))) + // Store length + mstore(result, length) } load(storagePointer, length, offset, memoryPointer); return result; } /** - * @notice Append raw bytes from storage at the given storagePointer, offset, and length to the given memoryPointer + * Append raw bytes from storage at the given storagePointer, offset, and length to the given memoryPointer */ function load(uint256 storagePointer, uint256 length, uint256 offset, uint256 memoryPointer) internal view { - // Support offsets that are greater than 32 bytes by incrementing the storagePointer and decrementing the offset - unchecked { - storagePointer += offset / 32; - offset %= 32; - } - - // For the first word, if there is an offset, apply a mask to beginning if (offset > 0) { - // Get the word's remaining length after the offset - uint256 wordRemainder; - // (safe because of `offset %= 32` at the start) - unchecked { - wordRemainder = 32 - offset; + // Support offsets that are greater than 32 bytes by incrementing the storagePointer and decrementing the offset + if (offset >= 32) { + unchecked { + storagePointer += offset / 32; + offset %= 32; + } } - uint256 mask = leftMask(wordRemainder); - /// @solidity memory-safe-assembly - assembly { - // Load data from storage and offset it to match memory - let offsetData := shl(mul(offset, 8), sload(storagePointer)) - - mstore( - memoryPointer, - or( - // store the middle part - and(offsetData, mask), - // preserve the surrounding parts - and(mload(memoryPointer), not(mask)) + // For the first word, if there is an offset, apply a mask to beginning + if (offset > 0) { + // Get the word's remaining length after the offset + uint256 wordRemainder; + // (safe because of `offset %= 32` at the start) + unchecked { + wordRemainder = 32 - offset; + } + + uint256 mask = leftMask(wordRemainder); + /// @solidity memory-safe-assembly + assembly { + // Load data from storage and offset it to match memory + let offsetData := shl(mul(offset, 8), sload(storagePointer)) + + mstore( + memoryPointer, + or( + // store the middle part + and(offsetData, mask), + // preserve the surrounding parts + and(mload(memoryPointer), not(mask)) + ) ) - ) - } - // Return if done - if (length <= wordRemainder) return; - - // Advance pointers - storagePointer += 1; - // (safe because of `length <= prefixLength` earlier) - unchecked { - memoryPointer += wordRemainder; - length -= wordRemainder; + } + // Return if done + if (length <= wordRemainder) return; + + // Advance pointers + // (safe because of `length <= wordRemainder` earlier) + unchecked { + storagePointer += 1; + memoryPointer += wordRemainder; + length -= wordRemainder; + } } } @@ -185,9 +185,8 @@ library Storage { assembly { mstore(memoryPointer, sload(storagePointer)) } - storagePointer += 1; - // (safe unless length is improbably large) unchecked { + storagePointer += 1; memoryPointer += 32; length -= 32; } diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index af8a8c6b71..251d5c7785 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -607,7 +607,7 @@ library StoreCoreInternal { // Store the provided value in storage uint256 dynamicDataLocation = _getDynamicDataLocation(tableId, key, dynamicSchemaIndex); - Storage.store({ storagePointer: dynamicDataLocation, data: data }); + Storage.store({ storagePointer: dynamicDataLocation, offset: 0, data: data }); } function _pushToDynamicField( @@ -731,7 +731,7 @@ library StoreCoreInternal { uint256 location = _getDynamicDataLocation(tableId, key, dynamicSchemaIndex); uint256 dataLength = _loadEncodedDynamicDataLength(tableId, key).atIndex(dynamicSchemaIndex); - return Storage.load({ storagePointer: location, length: dataLength }); + return Storage.load({ storagePointer: location, length: dataLength, offset: 0 }); } /************************************************************************ diff --git a/packages/store/test/Gas.t.sol b/packages/store/test/Gas.t.sol index 5d8c719976..884b019ebd 100644 --- a/packages/store/test/Gas.t.sol +++ b/packages/store/test/Gas.t.sol @@ -50,7 +50,7 @@ contract GasTest is Test, GasReporter { assertEq(abi.encode(abiDecoded), abi.encode(customDecoded)); } - function testCompareStorageSolidity() public { + function testCompareStorageWriteSolidity() public { (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) = SolidityStorage.generateValues(); ( SolidityStorage.LayoutSimple storage layoutSimple, @@ -85,30 +85,13 @@ contract GasTest is Test, GasReporter { startGasReport("solidity storage write (warm, 10 words)"); layoutBytes.value = value9Words; endGasReport(); - - // load - - startGasReport("solidity storage load (warm, 1 word)"); - valueSimple = layoutSimple.value; - endGasReport(); - - startGasReport("solidity storage load (warm, 1 word, partial)"); - valuePartial = layoutPartial.value; - endGasReport(); - - startGasReport("solidity storage load (warm, 10 words)"); - value9Words = layoutBytes.value; - endGasReport(); - - // Do something in case the optimizer removes unused assignments - someContract.doSomethingWithBytes(abi.encode(valueSimple, valuePartial, value9Words)); } // Note that this compares storage writes in isolation, which can be misleading, // since MUD encoding is dynamic and separate from storage, // but solidity encoding is hardcoded at compile-time and is part of writing to storage. // (look for comparison of native storage vs MUD tables for a more comprehensive overview) - function testCompareStorageMUD() public { + function testCompareStorageWriteMUD() public { (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) = SolidityStorage.generateValues(); bytes memory encodedSimple = abi.encodePacked(valueSimple); bytes memory encodedPartial = abi.encodePacked(valuePartial); @@ -141,23 +124,6 @@ contract GasTest is Test, GasReporter { startGasReport("MUD storage write (warm, 10 words)"); Storage.store(SolidityStorage.STORAGE_SLOT_BYTES, 0, encoded9Words); endGasReport(); - - // load - - startGasReport("MUD storage load (warm, 1 word)"); - encodedSimple = Storage.load(SolidityStorage.STORAGE_SLOT_SIMPLE, encodedSimple.length, 0); - endGasReport(); - - startGasReport("MUD storage load (warm, 1 word, partial)"); - encodedPartial = Storage.load(SolidityStorage.STORAGE_SLOT_PARTIAL, encodedPartial.length, 16); - endGasReport(); - - startGasReport("MUD storage load (warm, 10 words)"); - encoded9Words = Storage.load(SolidityStorage.STORAGE_SLOT_BYTES, encoded9Words.length, 0); - endGasReport(); - - // Do something in case the optimizer removes unused assignments - someContract.doSomethingWithBytes(abi.encode(encodedSimple, encodedPartial, encoded9Words)); } } diff --git a/packages/store/test/GasStorageLoad.t.sol b/packages/store/test/GasStorageLoad.t.sol new file mode 100644 index 0000000000..3991d25e12 --- /dev/null +++ b/packages/store/test/GasStorageLoad.t.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; +import { Storage } from "../src/Storage.sol"; +import { SolidityStorage, SomeContract } from "./Gas.t.sol"; + +contract GasStorageLoadTest is Test, GasReporter { + SomeContract someContract = new SomeContract(); + + // Cold loads require us to initialize the values outside of their test + function setUp() public { + (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) = SolidityStorage.generateValues(); + ( + SolidityStorage.LayoutSimple storage layoutSimple, + SolidityStorage.LayoutPartial storage layoutPartial, + SolidityStorage.LayoutBytes storage layoutBytes + ) = SolidityStorage.layouts(); + + layoutSimple.value = valueSimple; + layoutPartial.value = valuePartial; + layoutBytes.value = value9Words; + } + + function testCompareStorageLoadSolidity() public { + (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) = SolidityStorage.generateValues(); + ( + SolidityStorage.LayoutSimple storage layoutSimple, + SolidityStorage.LayoutPartial storage layoutPartial, + SolidityStorage.LayoutBytes storage layoutBytes + ) = SolidityStorage.layouts(); + + startGasReport("solidity storage load (cold, 1 word)"); + valueSimple = layoutSimple.value; + endGasReport(); + + startGasReport("solidity storage load (cold, 1 word, partial)"); + valuePartial = layoutPartial.value; + endGasReport(); + + startGasReport("solidity storage load (cold, 10 words)"); + value9Words = layoutBytes.value; + endGasReport(); + + // warm + + startGasReport("solidity storage load (warm, 1 word)"); + valueSimple = layoutSimple.value; + endGasReport(); + + startGasReport("solidity storage load (warm, 1 word, partial)"); + valuePartial = layoutPartial.value; + endGasReport(); + + startGasReport("solidity storage load (warm, 10 words)"); + value9Words = layoutBytes.value; + endGasReport(); + + // Do something in case the optimizer removes unused assignments + someContract.doSomethingWithBytes(abi.encode(valueSimple, valuePartial, value9Words)); + } + + function testCompareStorageLoadMUD() public { + (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) = SolidityStorage.generateValues(); + bytes memory encodedSimple = abi.encodePacked(valueSimple); + bytes memory encodedPartial = abi.encodePacked(valuePartial); + bytes memory encoded9Words = abi.encodePacked(value9Words.length, value9Words); + + startGasReport("MUD storage load (cold, 1 word)"); + encodedSimple = Storage.load(SolidityStorage.STORAGE_SLOT_SIMPLE, encodedSimple.length, 0); + endGasReport(); + + startGasReport("MUD storage load (cold, 1 word, partial)"); + encodedPartial = Storage.load(SolidityStorage.STORAGE_SLOT_PARTIAL, encodedPartial.length, 16); + endGasReport(); + + startGasReport("MUD storage load (cold, 10 words)"); + encoded9Words = Storage.load(SolidityStorage.STORAGE_SLOT_BYTES, encoded9Words.length, 0); + endGasReport(); + + // warm + + startGasReport("MUD storage load (warm, 1 word)"); + encodedSimple = Storage.load(SolidityStorage.STORAGE_SLOT_SIMPLE, encodedSimple.length, 0); + endGasReport(); + + startGasReport("MUD storage load (warm, 1 word, partial)"); + encodedPartial = Storage.load(SolidityStorage.STORAGE_SLOT_PARTIAL, encodedPartial.length, 16); + endGasReport(); + + startGasReport("MUD storage load (warm, 10 words)"); + encoded9Words = Storage.load(SolidityStorage.STORAGE_SLOT_BYTES, encoded9Words.length, 0); + endGasReport(); + + // Do something in case the optimizer removes unused assignments + someContract.doSomethingWithBytes(abi.encode(encodedSimple, encodedPartial, encoded9Words)); + } +} diff --git a/packages/store/test/Storage.t.sol b/packages/store/test/Storage.t.sol index fe8be775ed..1d6005aa6d 100644 --- a/packages/store/test/Storage.t.sol +++ b/packages/store/test/Storage.t.sol @@ -27,10 +27,10 @@ contract StorageTest is Test, GasReporter { // First store some data to storage at the target slot and two slots after the target slot startGasReport("store 1 storage slot"); - Storage.store({ storagePointer: storagePointer, data: originalDataFirstSlot }); + Storage.store({ storagePointer: storagePointer, offset: 0, data: originalDataFirstSlot }); endGasReport(); - Storage.store({ storagePointer: storagePointerTwoSlotsAfter, data: originalDataLastSlot }); + Storage.store({ storagePointer: storagePointerTwoSlotsAfter, offset: 0, data: originalDataLastSlot }); // Then set the target slot, partially overwriting the first and third slot, but using safeTrail and offset diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 36f0745446..e7a68eba2d 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,73 +3,73 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1255918 + "gasUsed": 1248704 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1255918 + "gasUsed": 1248704 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 189004 + "gasUsed": 187021 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1255918 + "gasUsed": 1248704 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1255918 + "gasUsed": 1248704 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 28442 + "gasUsed": 27801 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 270004 + "gasUsed": 262682 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1255918 + "gasUsed": 1248704 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 27056 + "gasUsed": 26415 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 141266 + "gasUsed": 137742 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 606592 + "gasUsed": 602496 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 7716 + "gasUsed": 7444 }, { "file": "test/KeysWithValueModule.t.sol", @@ -81,240 +81,240 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 606592 + "gasUsed": 602496 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 162059 + "gasUsed": 159927 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 606592 + "gasUsed": 602496 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 129713 + "gasUsed": 127327 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 50859 + "gasUsed": 49418 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 606592 + "gasUsed": 602496 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 170334 + "gasUsed": 168075 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 132692 + "gasUsed": 130339 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 163160 + "gasUsed": 160604 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 77029 + "gasUsed": 75381 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 222474 + "gasUsed": 220085 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 139829 + "gasUsed": 138370 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 139055 + "gasUsed": 137295 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 19621 + "gasUsed": 19014 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 31559 + "gasUsed": 31224 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 10806607 + "gasUsed": 10687510 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 1009010 + "gasUsed": 997013 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 9522 + "gasUsed": 9187 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 70209 + "gasUsed": 68939 }, { "file": "test/SnapSyncModule.t.sol", "test": "testSnapSyncGas", "name": "Call snap sync on a table with 1 record", - "gasUsed": 39819 + "gasUsed": 39143 }, { "file": "test/SnapSyncModule.t.sol", "test": "testSnapSyncGas", "name": "Call snap sync on a table with 2 records", - "gasUsed": 57129 + "gasUsed": 56220 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 797781 + "gasUsed": 791266 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 71099 + "gasUsed": 70073 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 769225 + "gasUsed": 763358 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 71099 + "gasUsed": 70073 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 15060 + "gasUsed": 14659 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 95419 + "gasUsed": 94777 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 81644 + "gasUsed": 80591 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 72828 + "gasUsed": 71771 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 102239 + "gasUsed": 101182 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 157623 + "gasUsed": 156426 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 88731 + "gasUsed": 87674 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 255729 + "gasUsed": 253992 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 43649 + "gasUsed": 43248 }, { "file": "test/World.t.sol", "test": "testSetMetadata", "name": "Set metadata", - "gasUsed": 279560 + "gasUsed": 278225 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 41504 + "gasUsed": 41103 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 38906 + "gasUsed": 38297 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 21696 + "gasUsed": 21087 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 41285 + "gasUsed": 40609 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 24487 + "gasUsed": 23811 } ] From 168a4cb43ce4f7bfbdb7b1b9d4c305b912a0d3f2 Mon Sep 17 00:00:00 2001 From: TheGreatAxios Date: Fri, 28 Jul 2023 07:39:43 -0700 Subject: [PATCH 7/9] fix(cli): add support for legacy transactions in deploy script (#1178) Co-authored-by: alvarius --- .changeset/afraid-hotels-bathe.md | 5 ++++ packages/cli/src/utils/deploy.ts | 38 ++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 .changeset/afraid-hotels-bathe.md diff --git a/.changeset/afraid-hotels-bathe.md b/.changeset/afraid-hotels-bathe.md new file mode 100644 index 0000000000..15ef0d2c31 --- /dev/null +++ b/.changeset/afraid-hotels-bathe.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/cli": patch +--- + +Add support for legacy transactions in deploy script by falling back to `gasPrice` if `lastBaseFeePerGas` is not available diff --git a/packages/cli/src/utils/deploy.ts b/packages/cli/src/utils/deploy.ts index 765cdf42ac..4d724a7196 100644 --- a/packages/cli/src/utils/deploy.ts +++ b/packages/cli/src/utils/deploy.ts @@ -59,8 +59,10 @@ export async function deploy( console.log("Initial nonce", nonce); // Compute maxFeePerGas and maxPriorityFeePerGas like ethers, but allow for a multiplier to allow replacing pending transactions - let maxPriorityFeePerGas: number; - let maxFeePerGas: BigNumber; + let maxPriorityFeePerGas: number | undefined; + let maxFeePerGas: BigNumber | undefined; + let gasPrice: BigNumber | undefined; + await setInternalFeePerGas(priorityFeeMultiplier); // Catch all to await any promises before exiting the script @@ -402,6 +404,7 @@ export async function deploy( nonce: nonce++, maxPriorityFeePerGas, maxFeePerGas, + gasPrice, }) .then((c) => (disableTxWait ? c : c.deployed())); @@ -497,7 +500,7 @@ export async function deploy( const gasLimit = await contract.estimateGas[func].apply(null, args); console.log(chalk.gray(`executing transaction: ${functionName} with nonce ${nonce}`)); const txPromise = contract[func] - .apply(null, [...args, { gasLimit, nonce: nonce++, maxPriorityFeePerGas, maxFeePerGas }]) + .apply(null, [...args, { gasLimit, nonce: nonce++, maxPriorityFeePerGas, maxFeePerGas, gasPrice }]) .then((tx: any) => (confirmations === 0 ? tx : tx.wait(confirmations))); promises.push(txPromise); return txPromise; @@ -542,15 +545,28 @@ export async function deploy( async function setInternalFeePerGas(multiplier: number) { // Compute maxFeePerGas and maxPriorityFeePerGas like ethers, but allow for a multiplier to allow replacing pending transactions const feeData = await provider.getFeeData(); - if (!feeData.lastBaseFeePerGas) throw new MUDError("Can not fetch lastBaseFeePerGas from RPC"); - if (!feeData.lastBaseFeePerGas.eq(0) && (await signer.getBalance()).eq(0)) { - throw new MUDError(`Attempting to deploy to a chain with non-zero base fee with an account that has no balance. -If you're deploying to the Lattice testnet, you can fund your account by running 'pnpm mud faucet --address ${await signer.getAddress()}'`); - } - // Set the priority fee to 0 for development chains with no base fee, to allow transactions from unfunded wallets - maxPriorityFeePerGas = feeData.lastBaseFeePerGas.eq(0) ? 0 : Math.floor(1_500_000_000 * multiplier); - maxFeePerGas = feeData.lastBaseFeePerGas.mul(2).add(maxPriorityFeePerGas); + if (feeData.lastBaseFeePerGas) { + if (!feeData.lastBaseFeePerGas.eq(0) && (await signer.getBalance()).eq(0)) { + throw new MUDError(`Attempting to deploy to a chain with non-zero base fee with an account that has no balance. + If you're deploying to the Lattice testnet, you can fund your account by running 'pnpm mud faucet --address ${await signer.getAddress()}'`); + } + + // Set the priority fee to 0 for development chains with no base fee, to allow transactions from unfunded wallets + maxPriorityFeePerGas = feeData.lastBaseFeePerGas.eq(0) ? 0 : Math.floor(1_500_000_000 * multiplier); + maxFeePerGas = feeData.lastBaseFeePerGas.mul(2).add(maxPriorityFeePerGas); + } else if (feeData.gasPrice) { + // Legacy chains with gasPrice instead of maxFeePerGas + if (!feeData.gasPrice.eq(0) && (await signer.getBalance()).eq(0)) { + throw new MUDError( + `Attempting to deploy to a chain with non-zero gas price with an account that has no balance.` + ); + } + + gasPrice = feeData.gasPrice; + } else { + throw new MUDError("Can not fetch fee data from RPC"); + } } } From 16d8c43e2678b29f513ca511dd97ca3346aadb1f Mon Sep 17 00:00:00 2001 From: LuckyWu Date: Mon, 31 Jul 2023 15:56:56 +0800 Subject: [PATCH 8/9] docs(world): fix minor bugs in the world docs (#1115) Co-authored-by: alvarius --- docs/pages/world/world-101.mdx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/pages/world/world-101.mdx b/docs/pages/world/world-101.mdx index 19618203cf..1c6c8663e3 100644 --- a/docs/pages/world/world-101.mdx +++ b/docs/pages/world/world-101.mdx @@ -222,12 +222,12 @@ Now we can import our new table, and write something to it. Let’s write a func // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { Dog } from "../codegen/tables/Dog.sol"; // import table we created +import { Dog, DogData } from "../codegen/tables/Dog.sol"; // import table we created contract MySystem is System { function addEntry(string memory name, string memory color) public returns (bytes32) { bytes32 key = bytes32(abi.encodePacked(block.number, msg.sender, gasleft())); // creating a random key for the record address owner = _msgSender(); // IMPORTANT: always refer to the msg.sender using the _msgSender() function - Dog.set(key, {owner: owner, name: name, color: color}); // creating our record! + Dog.set(key, DogData({owner: owner, name: name, color: color})); // creating our record! return key; } } @@ -235,6 +235,16 @@ contract MySystem is System { That’s it! `MySystem`, just like `IncrementSystem`, will have access to Dog given they are in the same namespace. + +We can run `pnpm mud worldgen` in the contract folder to recreate the systems. + +```bash +> pnpm mud worldgen +Generated system interface: src/codegen/world/IIncrementSystem.sol +Generated system interface: src/codegen/world/IMySystem.sol +Generated system interface: src/codegen/world/IWorld.sol +``` + After this step, the filesystem of the World is like this: ```bash From b24502cba68752938fed46f4cd3eadeb8499cdd9 Mon Sep 17 00:00:00 2001 From: dk1a Date: Mon, 31 Jul 2023 14:09:34 +0300 Subject: [PATCH 9/9] docs: prettier (#1213) --- docs/pages/world/world-101.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/world/world-101.mdx b/docs/pages/world/world-101.mdx index 1c6c8663e3..ebcb6df327 100644 --- a/docs/pages/world/world-101.mdx +++ b/docs/pages/world/world-101.mdx @@ -223,11 +223,12 @@ Now we can import our new table, and write something to it. Let’s write a func pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; import { Dog, DogData } from "../codegen/tables/Dog.sol"; // import table we created + contract MySystem is System { function addEntry(string memory name, string memory color) public returns (bytes32) { bytes32 key = bytes32(abi.encodePacked(block.number, msg.sender, gasleft())); // creating a random key for the record address owner = _msgSender(); // IMPORTANT: always refer to the msg.sender using the _msgSender() function - Dog.set(key, DogData({owner: owner, name: name, color: color})); // creating our record! + Dog.set(key, DogData({ owner: owner, name: name, color: color })); // creating our record! return key; } } @@ -235,7 +236,6 @@ contract MySystem is System { That’s it! `MySystem`, just like `IncrementSystem`, will have access to Dog given they are in the same namespace. - We can run `pnpm mud worldgen` in the contract folder to recreate the systems. ```bash