diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8544c06d..352c3d39 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: uses: foundry-rs/foundry-toolchain@v1 with: version: "nightly-ac81a53d1d5823919ffbadd3c65f081927aa11f2" - - run: dev/contracts/deploy-local + - run: contracts/dev/deploy-local - name: Run Tests run: | export GOPATH="${HOME}/go/" diff --git a/.vscode/settings.json b/.vscode/settings.json index 8918121c..684be825 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,5 +17,6 @@ ] }, "solidity.compileUsingRemoteVersion": "v0.8.28", - "solidity.formatter": "forge" + "solidity.formatter": "forge", + "wake.compiler.solc.remappings": [] } diff --git a/contracts/config/anvil_localnet/GroupMessages.json b/contracts/config/anvil_localnet/GroupMessages.json index 7ade0abb..1c217d30 100644 --- a/contracts/config/anvil_localnet/GroupMessages.json +++ b/contracts/config/anvil_localnet/GroupMessages.json @@ -1,10 +1,10 @@ { "addresses": { "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "groupMessagesImpl": "0x0a17FabeA4633ce714F1Fa4a2dcA62C3bAc4758d", - "groupMessagesProxy": "0x3C1Cb427D20F15563aDa8C249E71db76d7183B6c", + "groupMessagesImpl": "0x5f246ADDCF057E0f778CD422e20e413be70f9a0c", + "groupMessagesProxy": "0xaD82Ecf79e232B0391C5479C7f632aA1EA701Ed1", "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "deploymentBlock": 65, - "latestUpgradeBlock": 71 + "deploymentBlock": 160, + "latestUpgradeBlock": 160 } \ No newline at end of file diff --git a/contracts/config/anvil_localnet/IdentityUpdates.json b/contracts/config/anvil_localnet/IdentityUpdates.json index bcdaf689..bd96842c 100644 --- a/contracts/config/anvil_localnet/IdentityUpdates.json +++ b/contracts/config/anvil_localnet/IdentityUpdates.json @@ -1,10 +1,10 @@ { "addresses": { "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "identityUpdatesImpl": "0x1343248Cbd4e291C6979e70a138f4c774e902561", - "identityUpdatesProxy": "0x22a9B82A6c3D2BFB68F324B2e8367f346Dd6f32a", + "identityUpdatesImpl": "0x4Dd5336F3C0D70893A7a86c6aEBe9B953E87c891", + "identityUpdatesProxy": "0x91A1EeE63f300B8f41AE6AF67eDEa2e2ed8c3f79", "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "deploymentBlock": 67, - "latestUpgradeBlock": 67 + "deploymentBlock": 162, + "latestUpgradeBlock": 162 } \ No newline at end of file diff --git a/dev/contracts/deploy-local b/contracts/dev/deploy-local similarity index 60% rename from dev/contracts/deploy-local rename to contracts/dev/deploy-local index 6249f2c2..b6d0c656 100755 --- a/dev/contracts/deploy-local +++ b/contracts/dev/deploy-local @@ -1,14 +1,17 @@ #!/bin/bash # Deploy the smart contracts to the local anvil node set -euo pipefail -source dev/contracts/.env -source dev/contracts/common # Make sure the build directory exists mkdir -p ./build -# Move to working directory -cd ./contracts +# Always work from the contracts directory +script_dir=$(dirname "$(realpath "$0")") +repo_root=$(realpath "${script_dir}/../") +cd "${repo_root}" + +source dev/lib/env +source dev/lib/common # Update depencencies forge soldeer update &> /dev/null @@ -19,6 +22,4 @@ fi forge_deploy_script group_messages forge_deploy_script identity_updates - -# TODO: This should be a function in the forge CLI -deploy_contract src/Nodes.sol Nodes +forge_deploy_script nodes src/Nodes.sol Nodes diff --git a/dev/contracts/deploy-testnet b/contracts/dev/deploy-testnet similarity index 100% rename from dev/contracts/deploy-testnet rename to contracts/dev/deploy-testnet diff --git a/contracts/dev/generate b/contracts/dev/generate new file mode 100755 index 00000000..e97b3677 --- /dev/null +++ b/contracts/dev/generate @@ -0,0 +1,70 @@ +#!/bin/bash + +set -euo pipefail + +# Default directories (can be overridden with environment variables) +source_dir="${SOURCE_DIR:-src}" +build_dir="${BUILD_DIR:-build}" +output_dir="${OUTPUT_DIR:-pkg}" + +# Ensure required directories exist and clean up old artifacts +function setup_directories() { + mkdir -p "${build_dir}" "${output_dir}" +} + +# Generate bindings for a given contract +function generate_bindings() { + local filename="$1" + local package="$(echo "${filename}" | tr '[:upper:]' '[:lower:]')" + local source_artifact="${source_dir}/${filename}.sol" + local build_artifact="${build_dir}/${filename}" + local output_artifact="${output_dir}/${package}/${filename}.go" + + rm -f "${build_artifact}".*.json + mkdir -p "${output_dir}/${package}" + rm -f "${output_dir}/${package}"/*.go + + # Generate ABI and bytecode + if ! forge inspect "${source_artifact}:${filename}" abi > "${build_artifact}.abi.json"; then + echo "ERROR: Failed to generate ABI for ${filename}" >&2 + exit 1 + fi + + if ! forge inspect "${source_artifact}:${filename}" bytecode > "${build_artifact}.bin.json"; then + echo "ERROR: Failed to generate bytecode for ${filename}" >&2 + exit 1 + fi + + # Generate Go bindings + if ! abigen --abi "${build_artifact}.abi.json" \ + --bin "${build_artifact}.bin.json" \ + --pkg "${package}" \ + --type "${filename}" \ + --out "${output_artifact}" > /dev/null 2>&1; then + echo "ERROR: Failed to generate bindings for ${filename}" >&2 + exit 1 + fi +} + +function main() { + # Always work from the contracts directory + script_dir=$(dirname "$(realpath "$0")") + repo_root=$(realpath "${script_dir}/../") + cd "${repo_root}" + + setup_directories + + # Define contracts (pass as arguments or use a default list) + local contracts=("$@") + if [ "${#contracts[@]}" -eq 0 ]; then + contracts=("Nodes" "GroupMessages" "IdentityUpdates") + fi + + # Generate bindings for each contract + for contract in "${contracts[@]}"; do + echo "Processing contract: ${contract}" + generate_bindings "${contract}" + done +} + +main "$@" diff --git a/dev/contracts/common b/contracts/dev/lib/common similarity index 77% rename from dev/contracts/common rename to contracts/dev/lib/common index 4ab899ea..f5585254 100644 --- a/dev/contracts/common +++ b/contracts/dev/lib/common @@ -27,15 +27,17 @@ function forge_deploy_script() { echo -e "\n" ;; + nodes) + # TODO: Migrate to forge script + forge create --broadcast --legacy --json --rpc-url $DOCKER_RPC_URL --private-key $PRIVATE_KEY "$2:$3" > ../build/$3.json + echo -e "✅ Nodes contract deployed.\n" + cat ../build/$3.json + echo -e "\n" + ;; + *) echo "Invalid option. Use 'group_messages' or 'identity_updates'." exit 1 ;; esac } - -# Deploy a contract and save the output (which includes the contract address) to a JSON file to be used in tests -# TODO: This should be a function in the forge CLI -function deploy_contract() { - forge create --broadcast --legacy --json --rpc-url $DOCKER_RPC_URL --private-key $PRIVATE_KEY "$1:$2" > ../build/$2.json -} diff --git a/dev/contracts/.env b/contracts/dev/lib/env similarity index 100% rename from dev/contracts/.env rename to contracts/dev/lib/env diff --git a/pkg/abis/groupMessages.go b/contracts/pkg/groupmessages/GroupMessages.go similarity index 99% rename from pkg/abis/groupMessages.go rename to contracts/pkg/groupmessages/GroupMessages.go index 47355324..7f226ee9 100644 --- a/pkg/abis/groupMessages.go +++ b/contracts/pkg/groupmessages/GroupMessages.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package abis +package groupmessages import ( "errors" diff --git a/pkg/abis/identityUpdates.go b/contracts/pkg/identityupdates/IdentityUpdates.go similarity index 99% rename from pkg/abis/identityUpdates.go rename to contracts/pkg/identityupdates/IdentityUpdates.go index 1a1b5af4..c4a2d5d2 100644 --- a/pkg/abis/identityUpdates.go +++ b/contracts/pkg/identityupdates/IdentityUpdates.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package abis +package identityupdates import ( "errors" diff --git a/pkg/abis/nodes.go b/contracts/pkg/nodes/Nodes.go similarity index 99% rename from pkg/abis/nodes.go rename to contracts/pkg/nodes/Nodes.go index 68343855..69ea8657 100644 --- a/pkg/abis/nodes.go +++ b/contracts/pkg/nodes/Nodes.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package abis +package nodes import ( "errors" diff --git a/contracts/slither.config.json b/contracts/slither.config.json index 1df96896..c1bb202d 100644 --- a/contracts/slither.config.json +++ b/contracts/slither.config.json @@ -1,4 +1,4 @@ { - "detectors_to_exclude": "", + "detectors_to_exclude": "unused-state,naming-convention,constable-states", "filter_paths": "dependencies" } diff --git a/dev/baked/Dockerfile b/dev/baked/Dockerfile index dd09529c..b6e8a579 100644 --- a/dev/baked/Dockerfile +++ b/dev/baked/Dockerfile @@ -22,7 +22,7 @@ COPY . . # It seems that anvil flushes the file to disk on shutdown and it takes a few ms to be persisted # That gives us the pkill+sleep requirement RUN dev/docker/anvil-background && \ - dev/contracts/deploy-local && \ + contracts/dev/deploy-local && \ dev/register-local-node && \ dev/register-local-node-2 && \ pkill -f anvil && \ diff --git a/dev/contracts/deploy-ephemeral b/dev/contracts/deploy-ephemeral deleted file mode 100755 index 5bef356e..00000000 --- a/dev/contracts/deploy-ephemeral +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# Deploy the smart contracts to the local anvil node and log the resulting JSON - -source dev/contracts/.env - -cd ./contracts - -# Update depencencies -forge soldeer install - -forge create --legacy --json --broadcast --rpc-url $DOCKER_RPC_URL --private-key $PRIVATE_KEY "$1:$2" \ No newline at end of file diff --git a/dev/contracts/generate b/dev/contracts/generate deleted file mode 100755 index 9031c821..00000000 --- a/dev/contracts/generate +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -e - -PACKAGE_NAME="abis" -BUILD_DIR="build" -OUTPUT_DIR="pkg/abis" - -mkdir -p ./build -rm -f ./build/*.abi.json -rm -f ./pkg/abis/*.go - -function generate_bindings() { - cd contracts - forge inspect ./src/${1}.sol:${1} abi > ../${BUILD_DIR}/${1}.abi.json - forge inspect ./src/${1}.sol:${1} bytecode > ../${BUILD_DIR}/${1}.bin.json - - cd .. - abigen --abi ./${BUILD_DIR}/${1}.abi.json --bin ./${BUILD_DIR}/${1}.bin.json --pkg "${PACKAGE_NAME}" --type "${1}" --out "./${OUTPUT_DIR}/${1}.go" > /dev/null 2>&1 - -} - -for contract in Nodes GroupMessages IdentityUpdates; do - generate_bindings $contract -done diff --git a/dev/generate b/dev/generate index 8de689de..751f6cb6 100755 --- a/dev/generate +++ b/dev/generate @@ -6,5 +6,5 @@ set -euo pipefail sqlc generate go generate ./... rm -rf pkg/mocks/* -./dev/contracts/generate +./contracts/dev/generate mockery diff --git a/dev/local.env b/dev/local.env index f07ecaf4..38521690 100755 --- a/dev/local.env +++ b/dev/local.env @@ -1,6 +1,6 @@ #!/bin/bash -source dev/contracts/.env +source contracts/dev/lib/env # Anvil scripts output folder ANVIL_SCRIPTS_OUTPUT=contracts/config/anvil_localnet diff --git a/dev/up b/dev/up index a3f3da74..5edd05c5 100755 --- a/dev/up +++ b/dev/up @@ -28,8 +28,8 @@ fi dev/docker/up # Make sure the abis are updated -dev/contracts/generate -dev/contracts/deploy-local +contracts/dev/generate +contracts/dev/deploy-local echo "Registering local node-1" dev/register-local-node diff --git a/doc/deploy.md b/doc/deploy.md index 048995af..ca1a60fb 100644 --- a/doc/deploy.md +++ b/doc/deploy.md @@ -5,8 +5,9 @@ ## Deploy a new Contract The current environment lives in [Conduit Testnet Staging](https://explorer-testnet-staging-88dqtxdinc.t.conduit.xyz/). -To deploy a new contract you need to run `./dev/contracts/deploy-testnet` +To deploy a new contract you need to run `./contracts/dev/deploy-testnet` You will need: + - $PRIVATE_KEY which is accessible to all members of @ephemerahq/backend - $VERIFIER_URL: https://explorer-testnet-staging-88dqtxdinc.t.conduit.xyz/api - $RPC_URL: https://rpc-testnet-staging-88dqtxdinc.t.conduit.xyz/ @@ -18,6 +19,7 @@ We definitely need the node contract address (for example `0x7c9A7c92e21E9aC25Ce Before nodes can start or peer, they need to be registered with the contract. To do so, run: + ```shell export XMTPD_CONTRACTS_RPC_URL="https://rpc-testnet-staging-88dqtxdinc.t.conduit.xyz/" export XMTPD_CONTRACTS_CHAIN_ID=34498 @@ -36,6 +38,7 @@ You need to register all (both) nodes with their correct DNS entries and public ### Verify Registration To verify registration, use: + ```shell export XMTPD_CONTRACTS_RPC_URL="https://rpc-testnet-staging-88dqtxdinc.t.conduit.xyz/" export XMTPD_CONTRACTS_CHAIN_ID=34498 @@ -47,29 +50,29 @@ dev/cli get-all-nodes \ ``` And you should get something along these lines: + ```json { - "size": 2, - "nodes": [ - { - "NodeId": 100, - "Node": { - "SigningKeyPub": "BOVELF0f4vAra5oaOGODp3ZoYLQKYHmgIjmU/6LOEFEsToqIY97q2FnD1lQKsgJsgvi4k8HFvvbGP0fZ3zOiB9s=", - "HttpAddress": "https://grpc.testnet.xmtp.network", - "IsHealthy": true - } - }, - { - "NodeId": 200, - "Node": { - "SigningKeyPub": "BPwmHUOgFTU5pMZMKXY8sOfjd8DqwpEMPUvtsiNaxwNxz+fKU3SsqOdYJQDVjLfRL5XsA5XVZIge2WDZ7S0zpx4=", - "HttpAddress": "https://grpc2.testnet.xmtp.network", - "IsHealthy": true - } - } - ] + "size": 2, + "nodes": [ + { + "NodeId": 100, + "Node": { + "SigningKeyPub": "BOVELF0f4vAra5oaOGODp3ZoYLQKYHmgIjmU/6LOEFEsToqIY97q2FnD1lQKsgJsgvi4k8HFvvbGP0fZ3zOiB9s=", + "HttpAddress": "https://grpc.testnet.xmtp.network", + "IsHealthy": true + } + }, + { + "NodeId": 200, + "Node": { + "SigningKeyPub": "BPwmHUOgFTU5pMZMKXY8sOfjd8DqwpEMPUvtsiNaxwNxz+fKU3SsqOdYJQDVjLfRL5XsA5XVZIge2WDZ7S0zpx4=", + "HttpAddress": "https://grpc2.testnet.xmtp.network", + "IsHealthy": true + } + } + ] } - ``` ## Deploy XMTPD nodes @@ -78,9 +81,9 @@ Node deployment is currently fully handled by [Ephemera](https://github.com/ephe There are currently two nodes running: -| DNS Name | Location | Public Key | -| --- | ---| -- | -| https://grpc.testnet.xmtp.network | US-EAST-2 | 0x03e5442c5d1fe2f02b6b9a1a386383a7766860b40a6079a0223994ffa2ce10512c | +| DNS Name | Location | Public Key | +| ---------------------------------- | ---------- | -------------------------------------------------------------------- | +| https://grpc.testnet.xmtp.network | US-EAST-2 | 0x03e5442c5d1fe2f02b6b9a1a386383a7766860b40a6079a0223994ffa2ce10512c | | https://grpc2.testnet.xmtp.network | EU-NORTH-1 | 0x02fc261d43a0153539a4c64c29763cb0e7e377c0eac2910c3d4bedb2235ac70371 | For more info, refer to the infrastructure README. @@ -89,7 +92,6 @@ For more info, refer to the infrastructure README. The easiest way is to use [GRPC Health Probe](https://github.com/grpc-ecosystem/grpc-health-probe) - ```shell grpc-health-probe -tls -addr grpc.testnet.xmtp.network:443 status: SERVING diff --git a/pkg/api/payer/publish_test.go b/pkg/api/payer/publish_test.go index a2164454..499abd4e 100644 --- a/pkg/api/payer/publish_test.go +++ b/pkg/api/payer/publish_test.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" "github.com/xmtp/xmtpd/pkg/api/payer" "github.com/xmtp/xmtpd/pkg/envelopes" blockchainMocks "github.com/xmtp/xmtpd/pkg/mocks/blockchain" @@ -73,7 +73,7 @@ func TestPublishIdentityUpdate(t *testing.T) { mockMessagePublisher.EXPECT(). PublishIdentityUpdate(mock.Anything, mock.Anything, mock.Anything). - Return(&abis.IdentityUpdatesIdentityUpdateCreated{ + Return(&identityupdates.IdentityUpdatesIdentityUpdateCreated{ Raw: types.Log{ TxHash: txnHash, }, diff --git a/pkg/api/payer/service.go b/pkg/api/payer/service.go index 3a8d918a..8819d6ae 100644 --- a/pkg/api/payer/service.go +++ b/pkg/api/payer/service.go @@ -6,7 +6,8 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" "github.com/xmtp/xmtpd/pkg/blockchain" "github.com/xmtp/xmtpd/pkg/constants" "github.com/xmtp/xmtpd/pkg/envelopes" @@ -199,7 +200,7 @@ func (s *Service) publishToBlockchain( var hash common.Hash switch kind { case topic.TOPIC_KIND_GROUP_MESSAGES_V1: - var logMessage *abis.GroupMessagesMessageSent + var logMessage *groupmessages.GroupMessagesMessageSent if logMessage, err = s.blockchainPublisher.PublishGroupMessage(ctx, idBytes, payload); err != nil { return nil, status.Errorf(codes.Internal, "error publishing group message: %v", err) } @@ -215,7 +216,7 @@ func (s *Service) publishToBlockchain( ) case topic.TOPIC_KIND_IDENTITY_UPDATES_V1: - var logMessage *abis.IdentityUpdatesIdentityUpdateCreated + var logMessage *identityupdates.IdentityUpdatesIdentityUpdateCreated if logMessage, err = s.blockchainPublisher.PublishIdentityUpdate(ctx, idBytes, payload); err != nil { return nil, status.Errorf(codes.Internal, "error publishing identity update: %v", err) } diff --git a/pkg/blockchain/blockchainPublisher.go b/pkg/blockchain/blockchainPublisher.go index d648a2f8..0350dec9 100644 --- a/pkg/blockchain/blockchainPublisher.go +++ b/pkg/blockchain/blockchainPublisher.go @@ -13,7 +13,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" "github.com/xmtp/xmtpd/pkg/config" "go.uber.org/zap" ) @@ -24,8 +25,8 @@ Can publish to the blockchain, signing messages using the provided signer type BlockchainPublisher struct { signer TransactionSigner client *ethclient.Client - messagesContract *abis.GroupMessages - identityUpdateContract *abis.IdentityUpdates + messagesContract *groupmessages.GroupMessages + identityUpdateContract *identityupdates.IdentityUpdates logger *zap.Logger mutexNonce sync.Mutex nonce uint64 @@ -41,7 +42,7 @@ func NewBlockchainPublisher( if client == nil { return nil, errors.New("client is nil") } - messagesContract, err := abis.NewGroupMessages( + messagesContract, err := groupmessages.NewGroupMessages( common.HexToAddress(contractOptions.MessagesContractAddress), client, ) @@ -49,7 +50,7 @@ func NewBlockchainPublisher( if err != nil { return nil, err } - identityUpdateContract, err := abis.NewIdentityUpdates( + identityUpdateContract, err := identityupdates.NewIdentityUpdates( common.HexToAddress(contractOptions.IdentityUpdatesContractAddress), client, ) @@ -83,7 +84,7 @@ func (m *BlockchainPublisher) PublishGroupMessage( ctx context.Context, groupID [32]byte, message []byte, -) (*abis.GroupMessagesMessageSent, error) { +) (*groupmessages.GroupMessagesMessageSent, error) { if len(message) == 0 { return nil, errors.New("message is empty") } @@ -126,7 +127,7 @@ func (m *BlockchainPublisher) PublishIdentityUpdate( ctx context.Context, inboxId [32]byte, identityUpdate []byte, -) (*abis.IdentityUpdatesIdentityUpdateCreated, error) { +) (*identityupdates.IdentityUpdatesIdentityUpdateCreated, error) { if len(identityUpdate) == 0 { return nil, errors.New("identity update is empty") } diff --git a/pkg/blockchain/interface.go b/pkg/blockchain/interface.go index 78031b96..904e4f41 100644 --- a/pkg/blockchain/interface.go +++ b/pkg/blockchain/interface.go @@ -8,7 +8,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" ) // Construct a raw blockchain listener that can be used to listen for events across many contract event types @@ -50,10 +51,10 @@ type IBlockchainPublisher interface { ctx context.Context, inboxId [32]byte, identityUpdate []byte, - ) (*abis.IdentityUpdatesIdentityUpdateCreated, error) + ) (*identityupdates.IdentityUpdatesIdentityUpdateCreated, error) PublishGroupMessage( ctx context.Context, groupdId [32]byte, message []byte, - ) (*abis.GroupMessagesMessageSent, error) + ) (*groupmessages.GroupMessagesMessageSent, error) } diff --git a/pkg/blockchain/registryAdmin.go b/pkg/blockchain/registryAdmin.go index 2a009813..d99b1f51 100644 --- a/pkg/blockchain/registryAdmin.go +++ b/pkg/blockchain/registryAdmin.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/nodes" "github.com/xmtp/xmtpd/pkg/config" "go.uber.org/zap" ) @@ -24,7 +24,7 @@ A NodeRegistryAdmin is a struct responsible for calling admin functions on the n type NodeRegistryAdmin struct { client *ethclient.Client signer TransactionSigner - contract *abis.Nodes + contract *nodes.Nodes logger *zap.Logger } @@ -34,7 +34,7 @@ func NewNodeRegistryAdmin( signer TransactionSigner, contractsOptions config.ContractsOptions, ) (*NodeRegistryAdmin, error) { - contract, err := abis.NewNodes( + contract, err := nodes.NewNodes( common.HexToAddress(contractsOptions.NodesContractAddress), client, ) @@ -95,7 +95,7 @@ A NodeRegistryCaller is a struct responsible for calling public functions on the */ type NodeRegistryCaller struct { client *ethclient.Client - contract *abis.NodesCaller + contract *nodes.NodesCaller logger *zap.Logger } @@ -104,7 +104,7 @@ func NewNodeRegistryCaller( client *ethclient.Client, contractsOptions config.ContractsOptions, ) (*NodeRegistryCaller, error) { - contract, err := abis.NewNodesCaller( + contract, err := nodes.NewNodesCaller( common.HexToAddress(contractsOptions.NodesContractAddress), client, ) @@ -121,7 +121,7 @@ func NewNodeRegistryCaller( func (n *NodeRegistryCaller) GetAllNodes( ctx context.Context, -) ([]abis.NodesNodeWithId, error) { +) ([]nodes.NodesNodeWithId, error) { return n.contract.AllNodes(&bind.CallOpts{ Context: ctx, diff --git a/pkg/indexer/indexer.go b/pkg/indexer/indexer.go index 4034244c..c98e2859 100644 --- a/pkg/indexer/indexer.go +++ b/pkg/indexer/indexer.go @@ -11,7 +11,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" "github.com/xmtp/xmtpd/pkg/blockchain" "github.com/xmtp/xmtpd/pkg/config" "github.com/xmtp/xmtpd/pkg/db/queries" @@ -223,7 +224,7 @@ func indexLogs( } func buildMessagesTopic() (common.Hash, error) { - abi, err := abis.GroupMessagesMetaData.GetAbi() + abi, err := groupmessages.GroupMessagesMetaData.GetAbi() if err != nil { return common.Hash{}, err } @@ -231,7 +232,7 @@ func buildMessagesTopic() (common.Hash, error) { } func buildIdentityUpdatesTopic() (common.Hash, error) { - abi, err := abis.IdentityUpdatesMetaData.GetAbi() + abi, err := identityupdates.IdentityUpdatesMetaData.GetAbi() if err != nil { return common.Hash{}, err } @@ -241,8 +242,8 @@ func buildIdentityUpdatesTopic() (common.Hash, error) { func messagesContract( cfg config.ContractsOptions, client *ethclient.Client, -) (*abis.GroupMessages, error) { - return abis.NewGroupMessages( +) (*groupmessages.GroupMessages, error) { + return groupmessages.NewGroupMessages( common.HexToAddress(cfg.MessagesContractAddress), client, ) @@ -251,8 +252,8 @@ func messagesContract( func identityUpdatesContract( cfg config.ContractsOptions, client *ethclient.Client, -) (*abis.IdentityUpdates, error) { - return abis.NewIdentityUpdates( +) (*identityupdates.IdentityUpdates, error) { + return identityupdates.NewIdentityUpdates( common.HexToAddress(cfg.IdentityUpdatesContractAddress), client, ) diff --git a/pkg/indexer/storer/groupMessage.go b/pkg/indexer/storer/groupMessage.go index 472bb226..9c65a63b 100644 --- a/pkg/indexer/storer/groupMessage.go +++ b/pkg/indexer/storer/groupMessage.go @@ -5,7 +5,7 @@ import ( "errors" "github.com/ethereum/go-ethereum/core/types" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" "github.com/xmtp/xmtpd/pkg/db/queries" "github.com/xmtp/xmtpd/pkg/envelopes" "github.com/xmtp/xmtpd/pkg/topic" @@ -14,7 +14,7 @@ import ( ) type GroupMessageStorer struct { - contract *abis.GroupMessages + contract *groupmessages.GroupMessages queries *queries.Queries logger *zap.Logger } @@ -22,7 +22,7 @@ type GroupMessageStorer struct { func NewGroupMessageStorer( queries *queries.Queries, logger *zap.Logger, - contract *abis.GroupMessages, + contract *groupmessages.GroupMessages, ) *GroupMessageStorer { return &GroupMessageStorer{ queries: queries, diff --git a/pkg/indexer/storer/groupMessage_test.go b/pkg/indexer/storer/groupMessage_test.go index 3499486c..6e82ef6a 100644 --- a/pkg/indexer/storer/groupMessage_test.go +++ b/pkg/indexer/storer/groupMessage_test.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" "github.com/xmtp/xmtpd/pkg/blockchain" "github.com/xmtp/xmtpd/pkg/db/queries" "github.com/xmtp/xmtpd/pkg/envelopes" @@ -26,7 +26,7 @@ func buildGroupMessageStorer(t *testing.T) (*GroupMessageStorer, func()) { client, err := blockchain.NewClient(ctx, config.RpcUrl) require.NoError(t, err) - contract, err := abis.NewGroupMessages( + contract, err := groupmessages.NewGroupMessages( common.HexToAddress(contractAddress), client, ) @@ -122,7 +122,7 @@ func TestStoreGroupMessageMalformed(t *testing.T) { storer, cleanup := buildGroupMessageStorer(t) defer cleanup() - abi, err := abis.GroupMessagesMetaData.GetAbi() + abi, err := groupmessages.GroupMessagesMetaData.GetAbi() require.NoError(t, err) topic, err := utils.GetEventTopic(abi, "MessageSent") diff --git a/pkg/indexer/storer/identityUpdate.go b/pkg/indexer/storer/identityUpdate.go index b9719373..737923fc 100644 --- a/pkg/indexer/storer/identityUpdate.go +++ b/pkg/indexer/storer/identityUpdate.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/pingcap/log" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" "github.com/xmtp/xmtpd/pkg/db" "github.com/xmtp/xmtpd/pkg/db/queries" "github.com/xmtp/xmtpd/pkg/envelopes" @@ -27,7 +27,7 @@ const ( ) type IdentityUpdateStorer struct { - contract *abis.IdentityUpdates + contract *identityupdates.IdentityUpdates db *sql.DB logger *zap.Logger validationService mlsvalidate.MLSValidationService @@ -36,7 +36,7 @@ type IdentityUpdateStorer struct { func NewIdentityUpdateStorer( db *sql.DB, logger *zap.Logger, - contract *abis.IdentityUpdates, + contract *identityupdates.IdentityUpdates, validationService mlsvalidate.MLSValidationService, ) *IdentityUpdateStorer { return &IdentityUpdateStorer{ diff --git a/pkg/indexer/storer/identityUpdate_test.go b/pkg/indexer/storer/identityUpdate_test.go index c06fddb2..5426912c 100644 --- a/pkg/indexer/storer/identityUpdate_test.go +++ b/pkg/indexer/storer/identityUpdate_test.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" "github.com/xmtp/xmtpd/pkg/blockchain" "github.com/xmtp/xmtpd/pkg/db/queries" "github.com/xmtp/xmtpd/pkg/mlsvalidate" @@ -30,7 +30,7 @@ func buildIdentityUpdateStorer( client, err := blockchain.NewClient(ctx, config.RpcUrl) require.NoError(t, err) - contract, err := abis.NewIdentityUpdates( + contract, err := identityupdates.NewIdentityUpdates( common.HexToAddress(contractAddress), client, ) diff --git a/pkg/mocks/blockchain/mock_IBlockchainPublisher.go b/pkg/mocks/blockchain/mock_IBlockchainPublisher.go index dba74b98..37c1c50f 100644 --- a/pkg/mocks/blockchain/mock_IBlockchainPublisher.go +++ b/pkg/mocks/blockchain/mock_IBlockchainPublisher.go @@ -3,10 +3,11 @@ package blockchain import ( - abis "github.com/xmtp/xmtpd/pkg/abis" - context "context" + groupmessages "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" + identityupdates "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" + mock "github.com/stretchr/testify/mock" ) @@ -24,23 +25,23 @@ func (_m *MockIBlockchainPublisher) EXPECT() *MockIBlockchainPublisher_Expecter } // PublishGroupMessage provides a mock function with given fields: ctx, groupdId, message -func (_m *MockIBlockchainPublisher) PublishGroupMessage(ctx context.Context, groupdId [32]byte, message []byte) (*abis.GroupMessagesMessageSent, error) { +func (_m *MockIBlockchainPublisher) PublishGroupMessage(ctx context.Context, groupdId [32]byte, message []byte) (*groupmessages.GroupMessagesMessageSent, error) { ret := _m.Called(ctx, groupdId, message) if len(ret) == 0 { panic("no return value specified for PublishGroupMessage") } - var r0 *abis.GroupMessagesMessageSent + var r0 *groupmessages.GroupMessagesMessageSent var r1 error - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (*abis.GroupMessagesMessageSent, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (*groupmessages.GroupMessagesMessageSent, error)); ok { return rf(ctx, groupdId, message) } - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) *abis.GroupMessagesMessageSent); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) *groupmessages.GroupMessagesMessageSent); ok { r0 = rf(ctx, groupdId, message) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*abis.GroupMessagesMessageSent) + r0 = ret.Get(0).(*groupmessages.GroupMessagesMessageSent) } } @@ -73,34 +74,34 @@ func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) Run(run func(ctx co return _c } -func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) Return(_a0 *abis.GroupMessagesMessageSent, _a1 error) *MockIBlockchainPublisher_PublishGroupMessage_Call { +func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) Return(_a0 *groupmessages.GroupMessagesMessageSent, _a1 error) *MockIBlockchainPublisher_PublishGroupMessage_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (*abis.GroupMessagesMessageSent, error)) *MockIBlockchainPublisher_PublishGroupMessage_Call { +func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (*groupmessages.GroupMessagesMessageSent, error)) *MockIBlockchainPublisher_PublishGroupMessage_Call { _c.Call.Return(run) return _c } // PublishIdentityUpdate provides a mock function with given fields: ctx, inboxId, identityUpdate -func (_m *MockIBlockchainPublisher) PublishIdentityUpdate(ctx context.Context, inboxId [32]byte, identityUpdate []byte) (*abis.IdentityUpdatesIdentityUpdateCreated, error) { +func (_m *MockIBlockchainPublisher) PublishIdentityUpdate(ctx context.Context, inboxId [32]byte, identityUpdate []byte) (*identityupdates.IdentityUpdatesIdentityUpdateCreated, error) { ret := _m.Called(ctx, inboxId, identityUpdate) if len(ret) == 0 { panic("no return value specified for PublishIdentityUpdate") } - var r0 *abis.IdentityUpdatesIdentityUpdateCreated + var r0 *identityupdates.IdentityUpdatesIdentityUpdateCreated var r1 error - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (*abis.IdentityUpdatesIdentityUpdateCreated, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (*identityupdates.IdentityUpdatesIdentityUpdateCreated, error)); ok { return rf(ctx, inboxId, identityUpdate) } - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) *abis.IdentityUpdatesIdentityUpdateCreated); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) *identityupdates.IdentityUpdatesIdentityUpdateCreated); ok { r0 = rf(ctx, inboxId, identityUpdate) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*abis.IdentityUpdatesIdentityUpdateCreated) + r0 = ret.Get(0).(*identityupdates.IdentityUpdatesIdentityUpdateCreated) } } @@ -133,12 +134,12 @@ func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) Run(run func(ctx return _c } -func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) Return(_a0 *abis.IdentityUpdatesIdentityUpdateCreated, _a1 error) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { +func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) Return(_a0 *identityupdates.IdentityUpdatesIdentityUpdateCreated, _a1 error) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (*abis.IdentityUpdatesIdentityUpdateCreated, error)) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { +func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (*identityupdates.IdentityUpdatesIdentityUpdateCreated, error)) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { _c.Call.Return(run) return _c } diff --git a/pkg/mocks/registry/mock_NodesContract.go b/pkg/mocks/registry/mock_NodesContract.go index 423d4495..1027ee3f 100644 --- a/pkg/mocks/registry/mock_NodesContract.go +++ b/pkg/mocks/registry/mock_NodesContract.go @@ -5,7 +5,8 @@ package registry import ( bind "github.com/ethereum/go-ethereum/accounts/abi/bind" mock "github.com/stretchr/testify/mock" - abis "github.com/xmtp/xmtpd/pkg/abis" + + nodes "github.com/xmtp/xmtpd/contracts/pkg/nodes" ) // MockNodesContract is an autogenerated mock type for the NodesContract type @@ -22,23 +23,23 @@ func (_m *MockNodesContract) EXPECT() *MockNodesContract_Expecter { } // AllNodes provides a mock function with given fields: opts -func (_m *MockNodesContract) AllNodes(opts *bind.CallOpts) ([]abis.NodesNodeWithId, error) { +func (_m *MockNodesContract) AllNodes(opts *bind.CallOpts) ([]nodes.NodesNodeWithId, error) { ret := _m.Called(opts) if len(ret) == 0 { panic("no return value specified for AllNodes") } - var r0 []abis.NodesNodeWithId + var r0 []nodes.NodesNodeWithId var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]abis.NodesNodeWithId, error)); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]nodes.NodesNodeWithId, error)); ok { return rf(opts) } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []abis.NodesNodeWithId); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts) []nodes.NodesNodeWithId); ok { r0 = rf(opts) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]abis.NodesNodeWithId) + r0 = ret.Get(0).([]nodes.NodesNodeWithId) } } @@ -69,12 +70,12 @@ func (_c *MockNodesContract_AllNodes_Call) Run(run func(opts *bind.CallOpts)) *M return _c } -func (_c *MockNodesContract_AllNodes_Call) Return(_a0 []abis.NodesNodeWithId, _a1 error) *MockNodesContract_AllNodes_Call { +func (_c *MockNodesContract_AllNodes_Call) Return(_a0 []nodes.NodesNodeWithId, _a1 error) *MockNodesContract_AllNodes_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockNodesContract_AllNodes_Call) RunAndReturn(run func(*bind.CallOpts) ([]abis.NodesNodeWithId, error)) *MockNodesContract_AllNodes_Call { +func (_c *MockNodesContract_AllNodes_Call) RunAndReturn(run func(*bind.CallOpts) ([]nodes.NodesNodeWithId, error)) *MockNodesContract_AllNodes_Call { _c.Call.Return(run) return _c } diff --git a/pkg/registry/contractRegistry.go b/pkg/registry/contractRegistry.go index 56997b2c..c4215526 100644 --- a/pkg/registry/contractRegistry.go +++ b/pkg/registry/contractRegistry.go @@ -3,15 +3,16 @@ package registry import ( "context" "errors" - "github.com/xmtp/xmtpd/pkg/tracing" "strings" "sync" "time" + "github.com/xmtp/xmtpd/pkg/tracing" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/nodes" "github.com/xmtp/xmtpd/pkg/config" "go.uber.org/zap" ) @@ -53,7 +54,7 @@ func NewSmartContractRegistry( options config.ContractsOptions, ) (*SmartContractRegistry, error) { - contract, err := abis.NewNodesCaller( + contract, err := nodes.NewNodesCaller( common.HexToAddress(options.NodesContractAddress), ethclient, ) @@ -228,7 +229,7 @@ func (s *SmartContractRegistry) SetContractForTest(contract NodesContract) { s.contract = contract } -func convertNode(rawNode abis.NodesNodeWithId) Node { +func convertNode(rawNode nodes.NodesNodeWithId) Node { // Unmarshal the signing key. // If invalid, mark the config as being invalid as well. Clients should treat the // node as unhealthy in this case diff --git a/pkg/registry/contractRegistry_test.go b/pkg/registry/contractRegistry_test.go index 997b9caf..cb780ac4 100644 --- a/pkg/registry/contractRegistry_test.go +++ b/pkg/registry/contractRegistry_test.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/nodes" "github.com/xmtp/xmtpd/pkg/config" mocks "github.com/xmtp/xmtpd/pkg/mocks/registry" r "github.com/xmtp/xmtpd/pkg/registry" @@ -45,15 +45,15 @@ func TestContractRegistryNewNodes(t *testing.T) { mockContract := mocks.NewMockNodesContract(t) mockContract.EXPECT(). AllNodes(mock.Anything). - Return([]abis.NodesNodeWithId{ + Return([]nodes.NodesNodeWithId{ { NodeId: 1, - Node: abis.NodesNode{ + Node: nodes.NodesNode{ HttpAddress: "http://foo.com", SigningKeyPub: enc, }, }, - {NodeId: 2, Node: abis.NodesNode{HttpAddress: "https://bar.com", + {NodeId: 2, Node: nodes.NodesNode{HttpAddress: "https://bar.com", SigningKeyPub: enc}}, }, nil) @@ -88,15 +88,15 @@ func TestContractRegistryChangedNodes(t *testing.T) { // The first call, we'll set the address to foo.com. // Subsequent calls will set the address to bar.com mockContract.EXPECT(). - AllNodes(mock.Anything).RunAndReturn(func(*bind.CallOpts) ([]abis.NodesNodeWithId, error) { + AllNodes(mock.Anything).RunAndReturn(func(*bind.CallOpts) ([]nodes.NodesNodeWithId, error) { httpAddress := "http://foo.com" if !hasSentInitialValues { hasSentInitialValues = true } else { httpAddress = "http://bar.com" } - return []abis.NodesNodeWithId{ - {NodeId: 1, Node: abis.NodesNode{HttpAddress: httpAddress, SigningKeyPub: enc}}, + return []nodes.NodesNodeWithId{ + {NodeId: 1, Node: nodes.NodesNode{HttpAddress: httpAddress, SigningKeyPub: enc}}, }, nil }) @@ -134,11 +134,11 @@ func TestStopOnContextCancel(t *testing.T) { mockContract := mocks.NewMockNodesContract(t) mockContract.EXPECT(). AllNodes(mock.Anything). - RunAndReturn(func(*bind.CallOpts) ([]abis.NodesNodeWithId, error) { - return []abis.NodesNodeWithId{ + RunAndReturn(func(*bind.CallOpts) ([]nodes.NodesNodeWithId, error) { + return []nodes.NodesNodeWithId{ { NodeId: uint32(rand.Intn(1000)), - Node: abis.NodesNode{HttpAddress: "http://foo.com", SigningKeyPub: enc}, + Node: nodes.NodesNode{HttpAddress: "http://foo.com", SigningKeyPub: enc}, }, }, nil }) diff --git a/pkg/registry/interface.go b/pkg/registry/interface.go index 2aca4738..9d32c385 100644 --- a/pkg/registry/interface.go +++ b/pkg/registry/interface.go @@ -2,7 +2,7 @@ package registry import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/nodes" ) /* @@ -10,7 +10,7 @@ import ( A dumbed down interface of abis.NodesCaller for generating mocks */ type NodesContract interface { - AllNodes(opts *bind.CallOpts) ([]abis.NodesNodeWithId, error) + AllNodes(opts *bind.CallOpts) ([]nodes.NodesNodeWithId, error) } // Unregister the callback diff --git a/pkg/testutils/contracts.go b/pkg/testutils/contracts.go index 1282eb3d..1f128585 100644 --- a/pkg/testutils/contracts.go +++ b/pkg/testutils/contracts.go @@ -1,27 +1,39 @@ package testutils import ( - "bytes" - "encoding/json" - "os/exec" + "math/big" "testing" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/require" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" + "github.com/xmtp/xmtpd/contracts/pkg/identityupdates" + "github.com/xmtp/xmtpd/contracts/pkg/nodes" envelopesProto "github.com/xmtp/xmtpd/pkg/proto/xmtpv4/envelopes" "github.com/xmtp/xmtpd/pkg/utils" "google.golang.org/protobuf/proto" ) +const ( + ANVIL_LOCALNET_HOST = "http://localhost:7545" + ANVIL_LOCALNET_CHAIN_ID = 31337 + LOCAL_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + NODES_CONTRACT_NAME = "Nodes" + GROUP_MESSAGES_CONTRACT_NAME = "GroupMessages" + IDENTITY_UPDATES_CONTRACT_NAME = "IdentityUpdates" +) + // Build an abi encoded MessageSent event struct func BuildMessageSentEvent( groupID [32]byte, message []byte, sequenceID uint64, ) ([]byte, error) { - abi, err := abis.GroupMessagesMetaData.GetAbi() + abi, err := groupmessages.GroupMessagesMetaData.GetAbi() if err != nil { return nil, err } @@ -40,7 +52,7 @@ func BuildMessageSentLog( eventData, err := BuildMessageSentEvent(groupID, messageBytes, sequenceID) require.NoError(t, err) - abi, err := abis.GroupMessagesMetaData.GetAbi() + abi, err := groupmessages.GroupMessagesMetaData.GetAbi() require.NoError(t, err) topic, err := utils.GetEventTopic(abi, "MessageSent") @@ -53,7 +65,7 @@ func BuildMessageSentLog( } func BuildIdentityUpdateEvent(inboxId [32]byte, update []byte, sequenceID uint64) ([]byte, error) { - abi, err := abis.IdentityUpdatesMetaData.GetAbi() + abi, err := identityupdates.IdentityUpdatesMetaData.GetAbi() if err != nil { return nil, err } @@ -72,7 +84,7 @@ func BuildIdentityUpdateLog( eventData, err := BuildIdentityUpdateEvent(inboxId, messageBytes, sequenceID) require.NoError(t, err) - abi, err := abis.IdentityUpdatesMetaData.GetAbi() + abi, err := identityupdates.IdentityUpdatesMetaData.GetAbi() require.NoError(t, err) topic, err := utils.GetEventTopic(abi, "IdentityUpdateCreated") @@ -89,36 +101,45 @@ func BuildIdentityUpdateLog( Deploy a contract and return the contract's address. Will return a different address for each run, making it suitable for testing * */ -func deployContract(t *testing.T, filePath string, contractName string) string { - packageRoot := rootPath(t) - cmd := exec.Command("./dev/contracts/deploy-ephemeral", filePath, contractName) - cmd.Dir = packageRoot +func deployContract(t *testing.T, contractName string) string { + client, err := ethclient.Dial(ANVIL_LOCALNET_HOST) + require.NoError(t, err) - var out bytes.Buffer - var errors bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &errors + privateKey, err := crypto.HexToECDSA(LOCAL_PRIVATE_KEY) + require.NoError(t, err) - err := cmd.Run() - require.NoError(t, err, "Failed to execute deploy-ephemeral script", errors.String()) + auth, err := bind.NewKeyedTransactorWithChainID( + privateKey, + big.NewInt(ANVIL_LOCALNET_CHAIN_ID), + ) + require.NoError(t, err) - output := out.String() - t.Logf("deploy-ephemeral output: %s", output) + var addr common.Address + + switch contractName { + case NODES_CONTRACT_NAME: + addr, _, _, err = nodes.DeployNodes(auth, client) + case GROUP_MESSAGES_CONTRACT_NAME: + addr, _, _, err = groupmessages.DeployGroupMessages(auth, client) + case IDENTITY_UPDATES_CONTRACT_NAME: + addr, _, _, err = identityupdates.DeployIdentityUpdates(auth, client) + default: + t.Fatalf("Unknown contract name: %s", contractName) + } - var parsed contractInfo - require.NoError(t, json.Unmarshal([]byte(output), &parsed)) + require.NoError(t, err) - return parsed.DeployedTo + return addr.String() } func DeployNodesContract(t *testing.T) string { - return deployContract(t, "./src/Nodes.sol", "Nodes") + return deployContract(t, NODES_CONTRACT_NAME) } func DeployGroupMessagesContract(t *testing.T) string { - return deployContract(t, "./src/GroupMessages.sol", "GroupMessages") + return deployContract(t, GROUP_MESSAGES_CONTRACT_NAME) } func DeployIdentityUpdatesContract(t *testing.T) string { - return deployContract(t, "./src/IdentityUpdates.sol", "IdentityUpdates") + return deployContract(t, IDENTITY_UPDATES_CONTRACT_NAME) } diff --git a/pkg/utils/chainEvent_test.go b/pkg/utils/chainEvent_test.go index bb3d2eff..c0bb84e3 100644 --- a/pkg/utils/chainEvent_test.go +++ b/pkg/utils/chainEvent_test.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" - "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/contracts/pkg/groupmessages" ) const ( @@ -14,7 +14,7 @@ const ( ) func TestGetEventSignature(t *testing.T) { - abi, _ := abis.GroupMessagesMetaData.GetAbi() + abi, _ := groupmessages.GroupMessagesMetaData.GetAbi() signature, err := GetEventSig(abi, "MessageSent") require.NoError(t, err) @@ -22,7 +22,7 @@ func TestGetEventSignature(t *testing.T) { } func TestGetEventTopic(t *testing.T) { - abi, _ := abis.GroupMessagesMetaData.GetAbi() + abi, _ := groupmessages.GroupMessagesMetaData.GetAbi() topic, err := GetEventTopic(abi, "MessageSent") require.NoError(t, err)