From 7bdba85987a10433d7681ecf1640c5b04b685636 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 18 Jun 2024 15:33:09 +0100 Subject: [PATCH 1/9] feat: recursively find all `geth` deps of a set of root packages --- x/README.md | 3 + x/gethclone/README.md | 5 ++ x/gethclone/go.mod | 38 +++++++++++ x/gethclone/go.sum | 151 ++++++++++++++++++++++++++++++++++++++++++ x/gethclone/main.go | 117 ++++++++++++++++++++++++++++++++ 5 files changed, 314 insertions(+) create mode 100644 x/README.md create mode 100644 x/gethclone/README.md create mode 100644 x/gethclone/go.mod create mode 100644 x/gethclone/go.sum create mode 100644 x/gethclone/main.go diff --git a/x/README.md b/x/README.md new file mode 100644 index 0000000000..fdc9180621 --- /dev/null +++ b/x/README.md @@ -0,0 +1,3 @@ +# Experimental + +Code in this directory is experimental and MUST NOT be relied on to be stable. \ No newline at end of file diff --git a/x/gethclone/README.md b/x/gethclone/README.md new file mode 100644 index 0000000000..bdfcb0ece3 --- /dev/null +++ b/x/gethclone/README.md @@ -0,0 +1,5 @@ +# `gethclone` + +This is an experimental module for tracking upstream `go-ethereum` changes. +The approach of `git merge`ing the upstream branch into `subnet-evm` is brittle as it relies on purely syntactic patching. +`gethclone` is intended to follow a rebase-like pattern, applying a set of semantic patches (e.g. AST modification, [Uber's `gopatch`](https://pkg.go.dev/github.com/uber-go/gopatch), etc.) that (a) should be more robust to refactoring; and (b) act as explicit documentation of the diffs. \ No newline at end of file diff --git a/x/gethclone/go.mod b/x/gethclone/go.mod new file mode 100644 index 0000000000..bbcb96594c --- /dev/null +++ b/x/gethclone/go.mod @@ -0,0 +1,38 @@ +module github.com/ava-labs/subnet-evm/x/gethclone + +go 1.22.4 + +require ( + github.com/ava-labs/avalanchego v1.11.8 + github.com/ethereum/go-ethereum v1.13.8 + go.uber.org/multierr v1.10.0 + golang.org/x/tools v0.22.0 +) + +require ( + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/google/renameio/v2 v2.0.0 // indirect + github.com/gorilla/rpc v1.2.0 // indirect + github.com/holiman/uint256 v1.2.4 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/supranational/blst v0.3.11 // indirect + go.uber.org/mock v0.4.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + gonum.org/v1/gonum v0.11.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/x/gethclone/go.sum b/x/gethclone/go.sum new file mode 100644 index 0000000000..f425736336 --- /dev/null +++ b/x/gethclone/go.sum @@ -0,0 +1,151 @@ +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/ava-labs/avalanchego v1.11.8 h1:Q/der5bC/q3BQbIqxT7nNC0F30c+6X1G/eQzzMQ2CLk= +github.com/ava-labs/avalanchego v1.11.8/go.mod h1:aPYTETkM0KjtC7vFwPO6S8z2L0QTKaXjVUi98pTdNO4= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/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.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= +github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= +github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk= +github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.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.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= +github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/thepudds/fzgen v0.4.2 h1:HlEHl5hk2/cqEomf2uK5SA/FeJc12s/vIHmOG+FbACw= +github.com/thepudds/fzgen v0.4.2/go.mod h1:kHCWdsv5tdnt32NIHYDdgq083m6bMtaY0M+ipiO9xWE= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= +golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/x/gethclone/main.go b/x/gethclone/main.go new file mode 100644 index 0000000000..5fc3991ad5 --- /dev/null +++ b/x/gethclone/main.go @@ -0,0 +1,117 @@ +// The gethclone binary clones ethereum/go-ethereum Go packages, applying +// semantic patches. +package main + +import ( + "context" + "fmt" + "go/parser" + "go/token" + "log" + "os" + "path" + "strings" + + "github.com/ava-labs/avalanchego/utils/set" + "go.uber.org/multierr" + "golang.org/x/tools/go/packages" + + // TODO(arr4n): change to using a git sub-module + _ "github.com/ethereum/go-ethereum" +) + +func main() { + c := config{ + packages: []string{"core/vm"}, + } + // TODO(arr4n): add flags and parsing before running. + + log.SetOutput(os.Stderr) + log.Print("START") + if err := c.run(context.Background()); err != nil { + log.Fatal(err) + } + log.Print("DONE") +} + +type config struct { + packages []string + + processed map[string]bool +} + +const geth = "github.com/ethereum/go-ethereum/" + +func (c *config) run(ctx context.Context) error { + for i, p := range c.packages { + if !strings.HasPrefix(p, geth) { + c.packages[i] = path.Join(geth, p) + } + } + + c.processed = make(map[string]bool) + return c.loadAndParse(ctx, token.NewFileSet(), c.packages...) +} + +// loadAndParse loads all packages that match the `patterns` and individually +// passes them to `c.parse()`. +func (c *config) loadAndParse(ctx context.Context, fset *token.FileSet, patterns ...string) error { + if len(patterns) == 0 { + return nil + } + + pkgConfig := &packages.Config{ + Context: ctx, + Mode: packages.NeedName | packages.NeedCompiledGoFiles, + } + pkgs, err := packages.Load(pkgConfig, patterns...) + if err != nil { + return fmt.Errorf("packages.Load(..., %q): %v", c.packages, err) + } + + for _, pkg := range pkgs { + if err := c.parse(ctx, pkg, fset); err != nil { + return err + } + } + return nil +} + +// parse parses all `pkg.Files` into `fset`, transforms each according to +// semantic patches, and passes all geth imports back to `c.loadAndParse()` for +// recursive handling. +func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.FileSet) error { + if len(pkg.Errors) != 0 { + var err error + for _, e := range pkg.Errors { + multierr.AppendInto(&err, e) + } + return err + } + + if c.processed[pkg.PkgPath] { + return nil + } + c.processed[pkg.PkgPath] = true + log.Printf("Processing %q", pkg.PkgPath) + + allGethImports := set.NewSet[string](0) + for _, fName := range pkg.CompiledGoFiles { + file, err := parser.ParseFile(fset, fName, nil, parser.ParseComments|parser.SkipObjectResolution) + if err != nil { + return fmt.Errorf("parser.ParseFile(... %q ...): %v", fName, err) + } + + gethImports := set.NewSet[string](len(file.Imports)) + for _, im := range file.Imports { + if p := strings.Trim(im.Path.Value, `"`); strings.HasPrefix(p, geth) { + gethImports.Add(p) + } + } + allGethImports.Union(gethImports) + + // TODO(arr4n): add transformations + } + + return c.loadAndParse(ctx, fset, allGethImports.List()...) +} From bc958b480d1fcb18c8c09170c9cc966378eba0b6 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 18 Jun 2024 16:02:09 +0100 Subject: [PATCH 2/9] feat: add additional copyright + generated-code comment --- x/gethclone/copyright.go.txt | 14 ++++++++++++++ x/gethclone/main.go | 10 ++++++++++ 2 files changed, 24 insertions(+) create mode 100644 x/gethclone/copyright.go.txt diff --git a/x/gethclone/copyright.go.txt b/x/gethclone/copyright.go.txt new file mode 100644 index 0000000000..1c8b7b7cf3 --- /dev/null +++ b/x/gethclone/copyright.go.txt @@ -0,0 +1,14 @@ +// (c) 2019-2024, Ava Labs, Inc. +// +// This file is a derived work, based on the go-ethereum library whose original +// notices appear below. +// +// It is distributed under a license compatible with the licensing terms of the +// original code from which it is derived. +// +// Much love to the original authors for their work. +// ********** +// +// Code generated by gethclone - DO NOT EDIT. +// +// ********** \ No newline at end of file diff --git a/x/gethclone/main.go b/x/gethclone/main.go index 5fc3991ad5..6999ae95b0 100644 --- a/x/gethclone/main.go +++ b/x/gethclone/main.go @@ -5,6 +5,7 @@ package main import ( "context" "fmt" + "go/ast" "go/parser" "go/token" "log" @@ -16,6 +17,8 @@ import ( "go.uber.org/multierr" "golang.org/x/tools/go/packages" + _ "embed" + // TODO(arr4n): change to using a git sub-module _ "github.com/ethereum/go-ethereum" ) @@ -77,6 +80,9 @@ func (c *config) loadAndParse(ctx context.Context, fset *token.FileSet, patterns return nil } +//go:embed copyright.go.txt +var copyrightHeader string + // parse parses all `pkg.Files` into `fset`, transforms each according to // semantic patches, and passes all geth imports back to `c.loadAndParse()` for // recursive handling. @@ -110,6 +116,10 @@ func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.F } allGethImports.Union(gethImports) + file.Comments = append([]*ast.CommentGroup{{ + List: []*ast.Comment{{Text: copyrightHeader}}, + }}, file.Comments...) + // TODO(arr4n): add transformations } From 6d4c0d29c67a1f4c6c4f4361c395ec836c241060 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 18 Jun 2024 16:18:31 +0100 Subject: [PATCH 3/9] feat: replace all `github.com/ethereum/go-ethereum` import paths --- x/gethclone/main.go | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/x/gethclone/main.go b/x/gethclone/main.go index 6999ae95b0..c906f424c3 100644 --- a/x/gethclone/main.go +++ b/x/gethclone/main.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "go.uber.org/multierr" + "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/packages" _ "embed" @@ -23,9 +24,12 @@ import ( _ "github.com/ethereum/go-ethereum" ) +const geth = "github.com/ethereum/go-ethereum/" + func main() { c := config{ - packages: []string{"core/vm"}, + packages: []string{"core/vm"}, + outputModule: "github.com/ava-labs/subnet-evm/", } // TODO(arr4n): add flags and parsing before running. @@ -38,13 +42,12 @@ func main() { } type config struct { - packages []string + packages []string + outputModule string // TODO(arr4n): when writing output, use the same directory to source the module path processed map[string]bool } -const geth = "github.com/ethereum/go-ethereum/" - func (c *config) run(ctx context.Context) error { for i, p := range c.packages { if !strings.HasPrefix(p, geth) { @@ -108,11 +111,9 @@ func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.F return fmt.Errorf("parser.ParseFile(... %q ...): %v", fName, err) } - gethImports := set.NewSet[string](len(file.Imports)) - for _, im := range file.Imports { - if p := strings.Trim(im.Path.Value, `"`); strings.HasPrefix(p, geth) { - gethImports.Add(p) - } + gethImports, err := c.transformGethImports(fset, file) + if err != nil { + return nil } allGethImports.Union(gethImports) @@ -125,3 +126,22 @@ func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.F return c.loadAndParse(ctx, fset, allGethImports.List()...) } + +// transformGethImports finds all `ethereum/go-ethereum` imports in the file, +// converts their path to `c.outputModule`, and returns the set of transformed +// import paths. +func (c *config) transformGethImports(fset *token.FileSet, file *ast.File) (set.Set[string], error) { + imports := set.NewSet[string](len(file.Imports)) + for _, im := range file.Imports { + p := strings.Trim(im.Path.Value, `"`) + if !strings.HasPrefix(p, geth) { + continue + } + + imports.Add(p) + if !astutil.RewriteImport(fset, file, p, strings.Replace(p, geth, c.outputModule, 1)) { + return nil, fmt.Errorf("failed to rewrite import %q", p) + } + } + return imports, nil +} From 704468639d6ce708855ee3126d16d18b3463a309 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 18 Jun 2024 16:25:15 +0100 Subject: [PATCH 4/9] fix: use geth import already in `scripts/geth-allowed-packages.txt` --- x/gethclone/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/gethclone/main.go b/x/gethclone/main.go index c906f424c3..52fa51e509 100644 --- a/x/gethclone/main.go +++ b/x/gethclone/main.go @@ -21,7 +21,7 @@ import ( _ "embed" // TODO(arr4n): change to using a git sub-module - _ "github.com/ethereum/go-ethereum" + _ "github.com/ethereum/go-ethereum/common" ) const geth = "github.com/ethereum/go-ethereum/" From f67e79ae96d877b56c54ac0e13f71eeb6e3449ae Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Wed, 19 Jun 2024 10:48:00 +0100 Subject: [PATCH 5/9] feat: AST patching w/ package+type matching --- x/gethclone/ast_patch.go | 91 +++++++++++++++++++++++++ x/gethclone/ast_patch_test.go | 121 ++++++++++++++++++++++++++++++++++ x/gethclone/go.mod | 14 +--- x/gethclone/go.sum | 105 ++--------------------------- x/gethclone/main.go | 4 +- 5 files changed, 223 insertions(+), 112 deletions(-) create mode 100644 x/gethclone/ast_patch.go create mode 100644 x/gethclone/ast_patch_test.go diff --git a/x/gethclone/ast_patch.go b/x/gethclone/ast_patch.go new file mode 100644 index 0000000000..977282dbd3 --- /dev/null +++ b/x/gethclone/ast_patch.go @@ -0,0 +1,91 @@ +package main + +import ( + "go/ast" + "reflect" + + "golang.org/x/tools/go/ast/astutil" +) + +type ( + // An astPatch (optionally) modifies an AST node; it is equivalent to an + // `astutil.ApplyFunc` except that it returns an error instead of a boolean. + // A non-nil error is equivalent to returning false and will also abort all + // further calls to other patches. + astPatch func(*astutil.Cursor) error + // An astPatchRegistry maps [Go package path] -> [ast.Node concrete types] + // -> [all `astPatch` functions that must be applied to said node types in + // said package]. + // + // The special `pkgPath` value "*" will match all package paths. + astPatchRegistry map[string]map[reflect.Type][]astPatch +) + +// astPatches is a global astPatchRegistry. +var astPatches = make(astPatchRegistry) + +// add is a convenience wrapper for registering a new `astPatch` in the +// registry. The `zeroNode` can be any type (including nil pointers) that +// implements `ast.Node`. +// +// The special `pkgPath` value "*" will match all package paths. +func (r astPatchRegistry) add(pkgPath string, zeroNode ast.Node, fn astPatch) { + pkg, ok := r[pkgPath] + if !ok { + pkg = make(map[reflect.Type][]astPatch) + r[pkgPath] = pkg + } + + t := nodeType(zeroNode) + pkg[t] = append(pkg[t], fn) +} + +// apply calls `astutil.Apply()` on `node`, calling the appropriate `astPatch` +// functions as the syntax tree is traversed. Patches are applied as the `pre` +// argument to `astutil.Apply()`. +// +// Global `pkgPath` matches (i.e. to those registered with "*") will be applied +// before package-specific matches. +// +// If any patch returns an error then no further patches will be called, and the +// error will be returned by `apply()`. +func (r astPatchRegistry) apply(pkgPath string, node ast.Node) error { + var err error + astutil.Apply(node, func(c *astutil.Cursor) bool { + if err != nil { + return false + } + if err = r.applyToCursor("*", c); err != nil { + return false + } + err = r.applyToCursor(pkgPath, c) + return err == nil + }, nil) + return err +} + +// applyToCursor abstracts internal functionality from `r.apply()`; there should +// be no need to call it directly. +func (r astPatchRegistry) applyToCursor(pkgPath string, c *astutil.Cursor) error { + if c.Node() == nil { + return nil + } + + pkg, ok := r[pkgPath] + if !ok { + return nil + } + for _, fn := range pkg[nodeType(c.Node())] { + if err := fn(c); err != nil { + return err + } + } + return nil +} + +// nodeType returns the `reflect.Type` of the _concrete_ type implementing +// `ast.Node`. Simpy calling `reflect.TypeOf(n)` would be incorrect as it would +// reflect the interface (and not match any nodes). +func nodeType(n ast.Node) reflect.Type { + return reflect.ValueOf(n).Type() +} diff --git a/x/gethclone/ast_patch_test.go b/x/gethclone/ast_patch_test.go new file mode 100644 index 0000000000..d3249dbfe7 --- /dev/null +++ b/x/gethclone/ast_patch_test.go @@ -0,0 +1,121 @@ +package main + +import ( + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/token" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/tools/go/ast/astutil" +) + +type astPatchSpy struct { + gotFuncs, gotStructs []string +} + +const errorIfFuncName = "ErrorFuncName" + +var errFuncName = fmt.Errorf("encountered sentinel function %q", errorIfFuncName) + +func (s *astPatchSpy) funcRecorder(c *astutil.Cursor) error { + name := c.Node().(*ast.FuncDecl).Name.String() + if name == errorIfFuncName { + return errFuncName + } + s.gotFuncs = append(s.gotFuncs, name) + return nil +} + +func (s *astPatchSpy) structRecorder(c *astutil.Cursor) error { + switch p := c.Parent().(type) { + case *ast.TypeSpec: // it's a `type x struct` not, for example, a `map[T]struct{}` + s.gotStructs = append(s.gotStructs, p.Name.String()) + } + return nil +} + +func TestASTPatchRegistry(t *testing.T) { + tests := []struct { + name string + src string + wantErr error + wantFuncs, wantStructs []string + }{ + { + name: "happy path", + src: `package thepackage + +func FnA(){} + +func FnB(){} + +type StructA struct{} + +type StructB struct{} +`, + wantFuncs: []string{"FnA", "FnB"}, + wantStructs: []string{"StructA", "StructB"}, + }, + { + name: "error propagation", + src: `package thepackage + +func HappyFn() {} + +func ` + errorIfFuncName + `() {} +`, + wantErr: errFuncName, + wantFuncs: []string{"HappyFn"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var spy astPatchSpy + reg := make(astPatchRegistry) + + reg.add("*", &ast.FuncDecl{}, spy.funcRecorder) + const pkgPath = `github.com/the/repo/thepackage` + reg.add(pkgPath, &ast.StructType{}, spy.structRecorder) + + reg.add("unknown/package/path", &ast.FuncDecl{}, func(c *astutil.Cursor) error { + t.Errorf("unexpected call to %T with different package path", (astPatch)(nil)) + return nil + }) + + file := parseGoFile(t, token.NewFileSet(), tt.src) + bestEffortLogAST(t, file) + + // None of the `require.Equal*()` variants provide a check for exact + // match (i.e. equivalent to ==) of the identical error being + // propagated. + if gotErr := reg.apply(pkgPath, file); gotErr != tt.wantErr { + t.Fatalf("%T.apply(...) got err %v; want %v", reg, gotErr, tt.wantErr) + } + assert.Empty(t, cmp.Diff(tt.wantFuncs, spy.gotFuncs), "encountered function declarations (-want +got)") + assert.Empty(t, cmp.Diff(tt.wantStructs, spy.gotStructs), "encountered struct-type declarations (-want +got)") + }) + } +} + +func parseGoFile(tb testing.TB, fset *token.FileSet, src string) *ast.File { + tb.Helper() + f, err := parser.ParseFile(fset, "", src, parser.SkipObjectResolution) + require.NoError(tb, err, "Parsing Go source as file: parser.ParseFile([see logged source])") + return f +} + +func bestEffortLogAST(tb testing.TB, x any) { + tb.Helper() + + var buf bytes.Buffer + if err := ast.Fprint(&buf, nil, x, nil); err != nil { + return + } + tb.Logf("AST of parsed source:\n\n%s", buf.String()) +} diff --git a/x/gethclone/go.mod b/x/gethclone/go.mod index bbcb96594c..4a26fcddee 100644 --- a/x/gethclone/go.mod +++ b/x/gethclone/go.mod @@ -5,27 +5,19 @@ go 1.22.4 require ( github.com/ava-labs/avalanchego v1.11.8 github.com/ethereum/go-ethereum v1.13.8 + github.com/google/go-cmp v0.6.0 + github.com/stretchr/testify v1.8.4 go.uber.org/multierr v1.10.0 golang.org/x/tools v0.22.0 ) require ( - github.com/bits-and-blooms/bitset v1.10.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/google/renameio/v2 v2.0.0 // indirect github.com/gorilla/rpc v1.2.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect - github.com/supranational/blst v0.3.11 // indirect go.uber.org/mock v0.4.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect @@ -33,6 +25,6 @@ require ( golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/x/gethclone/go.sum b/x/gethclone/go.sum index f425736336..75ebf87f17 100644 --- a/x/gethclone/go.sum +++ b/x/gethclone/go.sum @@ -1,123 +1,36 @@ -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/ava-labs/avalanchego v1.11.8 h1:Q/der5bC/q3BQbIqxT7nNC0F30c+6X1G/eQzzMQ2CLk= github.com/ava-labs/avalanchego v1.11.8/go.mod h1:aPYTETkM0KjtC7vFwPO6S8z2L0QTKaXjVUi98pTdNO4= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= -github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/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.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= -github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= -github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk= github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= -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/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/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/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.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.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= -github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/thepudds/fzgen v0.4.2 h1:HlEHl5hk2/cqEomf2uK5SA/FeJc12s/vIHmOG+FbACw= github.com/thepudds/fzgen v0.4.2/go.mod h1:kHCWdsv5tdnt32NIHYDdgq083m6bMtaY0M+ipiO9xWE= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= @@ -132,20 +45,12 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/x/gethclone/main.go b/x/gethclone/main.go index 52fa51e509..4979beeba6 100644 --- a/x/gethclone/main.go +++ b/x/gethclone/main.go @@ -121,7 +121,9 @@ func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.F List: []*ast.Comment{{Text: copyrightHeader}}, }}, file.Comments...) - // TODO(arr4n): add transformations + if err := astPatches.apply(pkg.PkgPath, file); err != nil { + return fmt.Errorf("apply AST patches to %q: %v", pkg.PkgPath, err) + } } return c.loadAndParse(ctx, fset, allGethImports.List()...) From 59fc25f7a6c97a6259a0e4f093e0430bcb6d9c21 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Wed, 19 Jun 2024 11:53:24 +0100 Subject: [PATCH 6/9] refactor: abstract `astpatch` package --- .../{ast_patch.go => astpatch/astpatch.go} | 46 +++++++++---------- .../astpatch_test.go} | 26 +++++------ x/gethclone/main.go | 6 ++- 3 files changed, 41 insertions(+), 37 deletions(-) rename x/gethclone/{ast_patch.go => astpatch/astpatch.go} (53%) rename x/gethclone/{ast_patch_test.go => astpatch/astpatch_test.go} (80%) diff --git a/x/gethclone/ast_patch.go b/x/gethclone/astpatch/astpatch.go similarity index 53% rename from x/gethclone/ast_patch.go rename to x/gethclone/astpatch/astpatch.go index 977282dbd3..3bc6fd4e3a 100644 --- a/x/gethclone/ast_patch.go +++ b/x/gethclone/astpatch/astpatch.go @@ -1,4 +1,6 @@ -package main +// Package astpatch provides functionality for traversing and modifying Go +// syntax trees. It extends the astutil package with reusable "patches". +package astpatch import ( "go/ast" @@ -8,31 +10,31 @@ import ( ) type ( - // An astPatch (optionally) modifies an AST node; it is equivalent to an + // A Patch (optionally) modifies an AST node; it is equivalent to an // `astutil.ApplyFunc` except that it returns an error instead of a boolean. // A non-nil error is equivalent to returning false and will also abort all // further calls to other patches. - astPatch func(*astutil.Cursor) error - // An astPatchRegistry maps [Go package path] -> [ast.Node concrete types] - // -> [all `astPatch` functions that must be applied to said node types in - // said package]. + Patch func(*astutil.Cursor) error + // A PatchRegistry maps [Go package path] -> [ast.Node concrete types] -> + // [all `Patch` functions that must be applied to said node types in said + // package]. // // The special `pkgPath` value "*" will match all package paths. - astPatchRegistry map[string]map[reflect.Type][]astPatch + PatchRegistry map[string]map[reflect.Type][]Patch ) -// astPatches is a global astPatchRegistry. -var astPatches = make(astPatchRegistry) - -// add is a convenience wrapper for registering a new `astPatch` in the -// registry. The `zeroNode` can be any type (including nil pointers) that -// implements `ast.Node`. +// Add is a convenience wrapper for registering a new `Patch` in the registry. +// The `zeroNode` can be any type (including nil pointers) that implements +// `ast.Node`. // -// The special `pkgPath` value "*" will match all package paths. -func (r astPatchRegistry) add(pkgPath string, zeroNode ast.Node, fn astPatch) { +// The special `pkgPath` value "*" will match all package paths. While there is +// no specific requirement for `pkgPath` other than it matching the equivalent +// argument passed to `Apply()`, it is typically sourced from +// `golang.org/x/tools/go/packages.Package.PkgPath`. +func (r PatchRegistry) Add(pkgPath string, zeroNode ast.Node, fn Patch) { pkg, ok := r[pkgPath] if !ok { - pkg = make(map[reflect.Type][]astPatch) + pkg = make(map[reflect.Type][]Patch) r[pkgPath] = pkg } @@ -40,16 +42,16 @@ func (r astPatchRegistry) add(pkgPath string, zeroNode ast.Node, fn astPatch) { pkg[t] = append(pkg[t], fn) } -// apply calls `astutil.Apply()` on `node`, calling the appropriate `astPatch` +// Apply calls `astutil.Apply()` on `node`, calling the appropriate `Patch` // functions as the syntax tree is traversed. Patches are applied as the `pre` // argument to `astutil.Apply()`. // // Global `pkgPath` matches (i.e. to those registered with "*") will be applied // before package-specific matches. // -// If any patch returns an error then no further patches will be called, and the -// error will be returned by `apply()`. -func (r astPatchRegistry) apply(pkgPath string, node ast.Node) error { +// If any `Patch` returns an error then no further patches will be called, and +// the error will be returned by `Apply()`. +func (r PatchRegistry) Apply(pkgPath string, node ast.Node) error { var err error astutil.Apply(node, func(c *astutil.Cursor) bool { if err != nil { @@ -64,9 +66,7 @@ func (r astPatchRegistry) apply(pkgPath string, node ast.Node) error { return err } -// applyToCursor abstracts internal functionality from `r.apply()`; there should -// be no need to call it directly. -func (r astPatchRegistry) applyToCursor(pkgPath string, c *astutil.Cursor) error { +func (r PatchRegistry) applyToCursor(pkgPath string, c *astutil.Cursor) error { if c.Node() == nil { return nil } diff --git a/x/gethclone/ast_patch_test.go b/x/gethclone/astpatch/astpatch_test.go similarity index 80% rename from x/gethclone/ast_patch_test.go rename to x/gethclone/astpatch/astpatch_test.go index d3249dbfe7..22ad63af40 100644 --- a/x/gethclone/ast_patch_test.go +++ b/x/gethclone/astpatch/astpatch_test.go @@ -1,4 +1,4 @@ -package main +package astpatch import ( "bytes" @@ -14,7 +14,7 @@ import ( "golang.org/x/tools/go/ast/astutil" ) -type astPatchSpy struct { +type patchSpy struct { gotFuncs, gotStructs []string } @@ -22,7 +22,7 @@ const errorIfFuncName = "ErrorFuncName" var errFuncName = fmt.Errorf("encountered sentinel function %q", errorIfFuncName) -func (s *astPatchSpy) funcRecorder(c *astutil.Cursor) error { +func (s *patchSpy) funcRecorder(c *astutil.Cursor) error { name := c.Node().(*ast.FuncDecl).Name.String() if name == errorIfFuncName { return errFuncName @@ -31,7 +31,7 @@ func (s *astPatchSpy) funcRecorder(c *astutil.Cursor) error { return nil } -func (s *astPatchSpy) structRecorder(c *astutil.Cursor) error { +func (s *patchSpy) structRecorder(c *astutil.Cursor) error { switch p := c.Parent().(type) { case *ast.TypeSpec: // it's a `type x struct` not, for example, a `map[T]struct{}` s.gotStructs = append(s.gotStructs, p.Name.String()) @@ -39,7 +39,7 @@ func (s *astPatchSpy) structRecorder(c *astutil.Cursor) error { return nil } -func TestASTPatchRegistry(t *testing.T) { +func TestPatchRegistry(t *testing.T) { tests := []struct { name string src string @@ -76,15 +76,15 @@ func ` + errorIfFuncName + `() {} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - var spy astPatchSpy - reg := make(astPatchRegistry) + var spy patchSpy + reg := make(PatchRegistry) - reg.add("*", &ast.FuncDecl{}, spy.funcRecorder) + reg.Add("*", &ast.FuncDecl{}, spy.funcRecorder) const pkgPath = `github.com/the/repo/thepackage` - reg.add(pkgPath, &ast.StructType{}, spy.structRecorder) + reg.Add(pkgPath, &ast.StructType{}, spy.structRecorder) - reg.add("unknown/package/path", &ast.FuncDecl{}, func(c *astutil.Cursor) error { - t.Errorf("unexpected call to %T with different package path", (astPatch)(nil)) + reg.Add("unknown/package/path", &ast.FuncDecl{}, func(c *astutil.Cursor) error { + t.Errorf("unexpected call to %T with different package path", (Patch)(nil)) return nil }) @@ -94,8 +94,8 @@ func ` + errorIfFuncName + `() {} // None of the `require.Equal*()` variants provide a check for exact // match (i.e. equivalent to ==) of the identical error being // propagated. - if gotErr := reg.apply(pkgPath, file); gotErr != tt.wantErr { - t.Fatalf("%T.apply(...) got err %v; want %v", reg, gotErr, tt.wantErr) + if gotErr := reg.Apply(pkgPath, file); gotErr != tt.wantErr { + t.Fatalf("%T.Apply(...) got err %v; want %v", reg, gotErr, tt.wantErr) } assert.Empty(t, cmp.Diff(tt.wantFuncs, spy.gotFuncs), "encountered function declarations (-want +got)") assert.Empty(t, cmp.Diff(tt.wantStructs, spy.gotStructs), "encountered struct-type declarations (-want +got)") diff --git a/x/gethclone/main.go b/x/gethclone/main.go index 4979beeba6..69d9ceb046 100644 --- a/x/gethclone/main.go +++ b/x/gethclone/main.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/subnet-evm/x/gethclone/astpatch" "go.uber.org/multierr" "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/packages" @@ -30,6 +31,7 @@ func main() { c := config{ packages: []string{"core/vm"}, outputModule: "github.com/ava-labs/subnet-evm/", + astPatches: make(astpatch.PatchRegistry), } // TODO(arr4n): add flags and parsing before running. @@ -45,6 +47,8 @@ type config struct { packages []string outputModule string // TODO(arr4n): when writing output, use the same directory to source the module path + astPatches astpatch.PatchRegistry + processed map[string]bool } @@ -121,7 +125,7 @@ func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.F List: []*ast.Comment{{Text: copyrightHeader}}, }}, file.Comments...) - if err := astPatches.apply(pkg.PkgPath, file); err != nil { + if err := c.astPatches.Apply(pkg.PkgPath, file); err != nil { return fmt.Errorf("apply AST patches to %q: %v", pkg.PkgPath, err) } } From 4529a3b3713624174d6ae9935e5081c002c1ba04 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Wed, 19 Jun 2024 12:03:50 +0100 Subject: [PATCH 7/9] fix: false-positive geth import in linter --- scripts/lint_allowed_geth_imports.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/lint_allowed_geth_imports.sh b/scripts/lint_allowed_geth_imports.sh index 6603c86da6..ae26085f15 100755 --- a/scripts/lint_allowed_geth_imports.sh +++ b/scripts/lint_allowed_geth_imports.sh @@ -8,7 +8,7 @@ set -o pipefail # 1. Recursively search through all go files for any lines that include a direct import from go-ethereum # 2. Sort the unique results # #. Print out the difference between the search results and the list of specified allowed package imports from geth. -extra_imports=$(grep -r --include='*.go' --exclude-dir='simulator' '"github.com/ethereum/go-ethereum/.*"' -o -h | sort -u | comm -23 - ./scripts/geth-allowed-packages.txt) +extra_imports=$(grep -Pr --include='*.go' --exclude-dir='simulator' '^\s+"github.com/ethereum/go-ethereum/.*"' -o -h | tr -d '[:blank:]' | sort -u | comm -23 - ./scripts/geth-allowed-packages.txt) if [ -n "${extra_imports}" ]; then echo "new go-ethereum imports should be added to ./scripts/geth-allowed-packages.txt to prevent accidental imports:" echo "${extra_imports}" From df5d9e051dff7820e8f620cf59669bc36d2124f2 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Wed, 19 Jun 2024 13:14:25 +0100 Subject: [PATCH 8/9] feat: accept a `go.mod` file to describe output destination --- x/gethclone/go.mod | 3 ++- x/gethclone/go.sum | 2 ++ x/gethclone/main.go | 65 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/x/gethclone/go.mod b/x/gethclone/go.mod index 4a26fcddee..0c99cc4c69 100644 --- a/x/gethclone/go.mod +++ b/x/gethclone/go.mod @@ -6,8 +6,10 @@ require ( github.com/ava-labs/avalanchego v1.11.8 github.com/ethereum/go-ethereum v1.13.8 github.com/google/go-cmp v0.6.0 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 go.uber.org/multierr v1.10.0 + golang.org/x/mod v0.18.0 golang.org/x/tools v0.22.0 ) @@ -21,7 +23,6 @@ require ( go.uber.org/mock v0.4.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect - golang.org/x/mod v0.18.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect diff --git a/x/gethclone/go.sum b/x/gethclone/go.sum index 75ebf87f17..48b7852757 100644 --- a/x/gethclone/go.sum +++ b/x/gethclone/go.sum @@ -27,6 +27,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/thepudds/fzgen v0.4.2 h1:HlEHl5hk2/cqEomf2uK5SA/FeJc12s/vIHmOG+FbACw= diff --git a/x/gethclone/main.go b/x/gethclone/main.go index 69d9ceb046..a7db53f35d 100644 --- a/x/gethclone/main.go +++ b/x/gethclone/main.go @@ -6,16 +6,20 @@ import ( "context" "fmt" "go/ast" + "go/format" "go/parser" "go/token" "log" "os" "path" + "path/filepath" "strings" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/subnet-evm/x/gethclone/astpatch" + "github.com/spf13/pflag" "go.uber.org/multierr" + "golang.org/x/mod/modfile" "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/packages" @@ -25,15 +29,14 @@ import ( _ "github.com/ethereum/go-ethereum/common" ) -const geth = "github.com/ethereum/go-ethereum/" - func main() { c := config{ - packages: []string{"core/vm"}, - outputModule: "github.com/ava-labs/subnet-evm/", - astPatches: make(astpatch.PatchRegistry), + astPatches: make(astpatch.PatchRegistry), } - // TODO(arr4n): add flags and parsing before running. + + pflag.StringSliceVar(&c.packages, "packages", []string{"core/vm"}, `Geth packages to clone, with or without "github.com/ethereum/go-ethereum" prefix.`) + pflag.StringVar(&c.outputGoMod, "output_go_mod", "", "go.mod file of the destination to which geth will be cloned.") + pflag.Parse() log.SetOutput(os.Stderr) log.Print("START") @@ -44,14 +47,19 @@ func main() { } type config struct { - packages []string - outputModule string // TODO(arr4n): when writing output, use the same directory to source the module path + // Externally configurable (e.g. flags) + packages []string + outputGoMod string - astPatches astpatch.PatchRegistry + // Internal + outputModule *modfile.Module + astPatches astpatch.PatchRegistry processed map[string]bool } +const geth = "github.com/ethereum/go-ethereum" + func (c *config) run(ctx context.Context) error { for i, p := range c.packages { if !strings.HasPrefix(p, geth) { @@ -59,10 +67,25 @@ func (c *config) run(ctx context.Context) error { } } + mod, err := parseGoMod(c.outputGoMod) + fmt.Println(err) + if err != nil { + return nil + } + c.outputModule = mod.Module + c.processed = make(map[string]bool) return c.loadAndParse(ctx, token.NewFileSet(), c.packages...) } +func parseGoMod(filePath string) (*modfile.File, error) { + buf, err := os.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("parsing output go.mod: os.ReadFile(%q): %v", filePath, err) + } + return modfile.ParseLax(filePath, buf, nil) +} + // loadAndParse loads all packages that match the `patterns` and individually // passes them to `c.parse()`. func (c *config) loadAndParse(ctx context.Context, fset *token.FileSet, patterns ...string) error { @@ -106,7 +129,12 @@ func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.F return nil } c.processed[pkg.PkgPath] = true - log.Printf("Processing %q", pkg.PkgPath) + + outDir := filepath.Join( + filepath.Dir(c.outputGoMod), + strings.TrimPrefix(pkg.PkgPath, geth), + ) + log.Printf("Cloning %q into %q", pkg.PkgPath, outDir) allGethImports := set.NewSet[string](0) for _, fName := range pkg.CompiledGoFiles { @@ -128,6 +156,21 @@ func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.F if err := c.astPatches.Apply(pkg.PkgPath, file); err != nil { return fmt.Errorf("apply AST patches to %q: %v", pkg.PkgPath, err) } + + if false { + // TODO(arr4n): enable writing when a suitable strategy exists; in + // the meantime, this code is demonstrative of intent. Do we want to + // simply overwrite and then check `git diff`? Do we want to check + // the diffs here? + outFile := filepath.Join(outDir, filepath.Base(fName)) + f, err := os.Create(outFile) + if err != nil { + return err + } + if err := format.Node(f, fset, file); err != nil { + return err + } + } } return c.loadAndParse(ctx, fset, allGethImports.List()...) @@ -145,7 +188,7 @@ func (c *config) transformGethImports(fset *token.FileSet, file *ast.File) (set. } imports.Add(p) - if !astutil.RewriteImport(fset, file, p, strings.Replace(p, geth, c.outputModule, 1)) { + if !astutil.RewriteImport(fset, file, p, strings.Replace(p, geth, c.outputModule.Mod.String(), 1)) { return nil, fmt.Errorf("failed to rewrite import %q", p) } } From 8df8e0965a0376a6ab94479256f35fa2fdddd8a9 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Wed, 19 Jun 2024 17:09:31 +0100 Subject: [PATCH 9/9] refactor: `config` and methods into separate file for minimal entrypoint `main.go` --- x/gethclone/gethclone.go | 176 +++++++++++++++++++++++++++++++++++++++ x/gethclone/main.go | 167 ------------------------------------- 2 files changed, 176 insertions(+), 167 deletions(-) create mode 100644 x/gethclone/gethclone.go diff --git a/x/gethclone/gethclone.go b/x/gethclone/gethclone.go new file mode 100644 index 0000000000..1828df9c61 --- /dev/null +++ b/x/gethclone/gethclone.go @@ -0,0 +1,176 @@ +package main + +import ( + "context" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "log" + "os" + "path" + "path/filepath" + "strings" + + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/subnet-evm/x/gethclone/astpatch" + "go.uber.org/multierr" + "golang.org/x/mod/modfile" + "golang.org/x/tools/go/ast/astutil" + "golang.org/x/tools/go/packages" + + _ "embed" + + // TODO(arr4n): change to using a git sub-module + _ "github.com/ethereum/go-ethereum/common" +) + +type config struct { + // Externally configurable (e.g. flags) + packages []string + outputGoMod string + + // Internal + outputModule *modfile.Module + astPatches astpatch.PatchRegistry + + processed map[string]bool +} + +const geth = "github.com/ethereum/go-ethereum" + +func (c *config) run(ctx context.Context) error { + for i, p := range c.packages { + if !strings.HasPrefix(p, geth) { + c.packages[i] = path.Join(geth, p) + } + } + + mod, err := parseGoMod(c.outputGoMod) + fmt.Println(err) + if err != nil { + return nil + } + c.outputModule = mod.Module + + c.processed = make(map[string]bool) + return c.loadAndParse(ctx, token.NewFileSet(), c.packages...) +} + +func parseGoMod(filePath string) (*modfile.File, error) { + buf, err := os.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("parsing output go.mod: os.ReadFile(%q): %v", filePath, err) + } + return modfile.ParseLax(filePath, buf, nil) +} + +// loadAndParse loads all packages that match the `patterns` and individually +// passes them to `c.parse()`. +func (c *config) loadAndParse(ctx context.Context, fset *token.FileSet, patterns ...string) error { + if len(patterns) == 0 { + return nil + } + + pkgConfig := &packages.Config{ + Context: ctx, + Mode: packages.NeedName | packages.NeedCompiledGoFiles, + } + pkgs, err := packages.Load(pkgConfig, patterns...) + if err != nil { + return fmt.Errorf("packages.Load(..., %q): %v", c.packages, err) + } + + for _, pkg := range pkgs { + if err := c.parse(ctx, pkg, fset); err != nil { + return err + } + } + return nil +} + +//go:embed copyright.go.txt +var copyrightHeader string + +// parse parses all `pkg.Files` into `fset`, transforms each according to +// semantic patches, and passes all geth imports back to `c.loadAndParse()` for +// recursive handling. +func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.FileSet) error { + if len(pkg.Errors) != 0 { + var err error + for _, e := range pkg.Errors { + multierr.AppendInto(&err, e) + } + return err + } + + if c.processed[pkg.PkgPath] { + return nil + } + c.processed[pkg.PkgPath] = true + + outDir := filepath.Join( + filepath.Dir(c.outputGoMod), + strings.TrimPrefix(pkg.PkgPath, geth), + ) + log.Printf("Cloning %q into %q", pkg.PkgPath, outDir) + + allGethImports := set.NewSet[string](0) + for _, fName := range pkg.CompiledGoFiles { + file, err := parser.ParseFile(fset, fName, nil, parser.ParseComments|parser.SkipObjectResolution) + if err != nil { + return fmt.Errorf("parser.ParseFile(... %q ...): %v", fName, err) + } + + gethImports, err := c.transformGethImports(fset, file) + if err != nil { + return nil + } + allGethImports.Union(gethImports) + + file.Comments = append([]*ast.CommentGroup{{ + List: []*ast.Comment{{Text: copyrightHeader}}, + }}, file.Comments...) + + if err := c.astPatches.Apply(pkg.PkgPath, file); err != nil { + return fmt.Errorf("apply AST patches to %q: %v", pkg.PkgPath, err) + } + + if false { + // TODO(arr4n): enable writing when a suitable strategy exists; in + // the meantime, this code is demonstrative of intent. Do we want to + // simply overwrite and then check `git diff`? Do we want to check + // the diffs here? + outFile := filepath.Join(outDir, filepath.Base(fName)) + f, err := os.Create(outFile) + if err != nil { + return err + } + if err := format.Node(f, fset, file); err != nil { + return err + } + } + } + + return c.loadAndParse(ctx, fset, allGethImports.List()...) +} + +// transformGethImports finds all `ethereum/go-ethereum` imports in the file, +// converts their path to `c.outputModule`, and returns the set of transformed +// import paths. +func (c *config) transformGethImports(fset *token.FileSet, file *ast.File) (set.Set[string], error) { + imports := set.NewSet[string](len(file.Imports)) + for _, im := range file.Imports { + p := strings.Trim(im.Path.Value, `"`) + if !strings.HasPrefix(p, geth) { + continue + } + + imports.Add(p) + if !astutil.RewriteImport(fset, file, p, strings.Replace(p, geth, c.outputModule.Mod.String(), 1)) { + return nil, fmt.Errorf("failed to rewrite import %q", p) + } + } + return imports, nil +} diff --git a/x/gethclone/main.go b/x/gethclone/main.go index a7db53f35d..c24516f18f 100644 --- a/x/gethclone/main.go +++ b/x/gethclone/main.go @@ -4,29 +4,11 @@ package main import ( "context" - "fmt" - "go/ast" - "go/format" - "go/parser" - "go/token" "log" "os" - "path" - "path/filepath" - "strings" - "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/subnet-evm/x/gethclone/astpatch" "github.com/spf13/pflag" - "go.uber.org/multierr" - "golang.org/x/mod/modfile" - "golang.org/x/tools/go/ast/astutil" - "golang.org/x/tools/go/packages" - - _ "embed" - - // TODO(arr4n): change to using a git sub-module - _ "github.com/ethereum/go-ethereum/common" ) func main() { @@ -45,152 +27,3 @@ func main() { } log.Print("DONE") } - -type config struct { - // Externally configurable (e.g. flags) - packages []string - outputGoMod string - - // Internal - outputModule *modfile.Module - astPatches astpatch.PatchRegistry - - processed map[string]bool -} - -const geth = "github.com/ethereum/go-ethereum" - -func (c *config) run(ctx context.Context) error { - for i, p := range c.packages { - if !strings.HasPrefix(p, geth) { - c.packages[i] = path.Join(geth, p) - } - } - - mod, err := parseGoMod(c.outputGoMod) - fmt.Println(err) - if err != nil { - return nil - } - c.outputModule = mod.Module - - c.processed = make(map[string]bool) - return c.loadAndParse(ctx, token.NewFileSet(), c.packages...) -} - -func parseGoMod(filePath string) (*modfile.File, error) { - buf, err := os.ReadFile(filePath) - if err != nil { - return nil, fmt.Errorf("parsing output go.mod: os.ReadFile(%q): %v", filePath, err) - } - return modfile.ParseLax(filePath, buf, nil) -} - -// loadAndParse loads all packages that match the `patterns` and individually -// passes them to `c.parse()`. -func (c *config) loadAndParse(ctx context.Context, fset *token.FileSet, patterns ...string) error { - if len(patterns) == 0 { - return nil - } - - pkgConfig := &packages.Config{ - Context: ctx, - Mode: packages.NeedName | packages.NeedCompiledGoFiles, - } - pkgs, err := packages.Load(pkgConfig, patterns...) - if err != nil { - return fmt.Errorf("packages.Load(..., %q): %v", c.packages, err) - } - - for _, pkg := range pkgs { - if err := c.parse(ctx, pkg, fset); err != nil { - return err - } - } - return nil -} - -//go:embed copyright.go.txt -var copyrightHeader string - -// parse parses all `pkg.Files` into `fset`, transforms each according to -// semantic patches, and passes all geth imports back to `c.loadAndParse()` for -// recursive handling. -func (c *config) parse(ctx context.Context, pkg *packages.Package, fset *token.FileSet) error { - if len(pkg.Errors) != 0 { - var err error - for _, e := range pkg.Errors { - multierr.AppendInto(&err, e) - } - return err - } - - if c.processed[pkg.PkgPath] { - return nil - } - c.processed[pkg.PkgPath] = true - - outDir := filepath.Join( - filepath.Dir(c.outputGoMod), - strings.TrimPrefix(pkg.PkgPath, geth), - ) - log.Printf("Cloning %q into %q", pkg.PkgPath, outDir) - - allGethImports := set.NewSet[string](0) - for _, fName := range pkg.CompiledGoFiles { - file, err := parser.ParseFile(fset, fName, nil, parser.ParseComments|parser.SkipObjectResolution) - if err != nil { - return fmt.Errorf("parser.ParseFile(... %q ...): %v", fName, err) - } - - gethImports, err := c.transformGethImports(fset, file) - if err != nil { - return nil - } - allGethImports.Union(gethImports) - - file.Comments = append([]*ast.CommentGroup{{ - List: []*ast.Comment{{Text: copyrightHeader}}, - }}, file.Comments...) - - if err := c.astPatches.Apply(pkg.PkgPath, file); err != nil { - return fmt.Errorf("apply AST patches to %q: %v", pkg.PkgPath, err) - } - - if false { - // TODO(arr4n): enable writing when a suitable strategy exists; in - // the meantime, this code is demonstrative of intent. Do we want to - // simply overwrite and then check `git diff`? Do we want to check - // the diffs here? - outFile := filepath.Join(outDir, filepath.Base(fName)) - f, err := os.Create(outFile) - if err != nil { - return err - } - if err := format.Node(f, fset, file); err != nil { - return err - } - } - } - - return c.loadAndParse(ctx, fset, allGethImports.List()...) -} - -// transformGethImports finds all `ethereum/go-ethereum` imports in the file, -// converts their path to `c.outputModule`, and returns the set of transformed -// import paths. -func (c *config) transformGethImports(fset *token.FileSet, file *ast.File) (set.Set[string], error) { - imports := set.NewSet[string](len(file.Imports)) - for _, im := range file.Imports { - p := strings.Trim(im.Path.Value, `"`) - if !strings.HasPrefix(p, geth) { - continue - } - - imports.Add(p) - if !astutil.RewriteImport(fset, file, p, strings.Replace(p, geth, c.outputModule.Mod.String(), 1)) { - return nil, fmt.Errorf("failed to rewrite import %q", p) - } - } - return imports, nil -}