diff --git a/docker/signer-example.Dockerfile b/docker/signer-example.Dockerfile new file mode 100644 index 0000000000..aa3565930a --- /dev/null +++ b/docker/signer-example.Dockerfile @@ -0,0 +1,15 @@ +FROM gcr.io/distroless/static:latest + +LABEL org.label-schema.description="signer-example Docker Image" +LABEL org.label-schema.name="ghcr.io/synapsecns/sanguine/contrib/signer-example" +LABEL org.label-schema.schema-version="1.0.0" +LABEL org.label-schema.vcs-url="https://github.com/synapsecns/sanguine" +LABEL org.opencontainers.image.source="https://github.com/synapsecns/sanguine" +LABEL org.opencontainers.image.description="signer-example Docker image" + +USER nonroot:nonroot + +WORKDIR /app +COPY --chown=nonroot:nonroot signer-example /app/signer-example + +ENTRYPOINT ["/app/signer-example"] diff --git a/docs/bridge/docs/Services/Signer.md b/docs/bridge/docs/Services/Signer.md index 7bf49d57fe..7dc96a934b 100644 --- a/docs/bridge/docs/Services/Signer.md +++ b/docs/bridge/docs/Services/Signer.md @@ -1,3 +1,136 @@ # Signer +## Setup with AWS KMS + +In order to setup the signer with AWS KMS, you will need to create a KMS key and give the appropriate permissions to a user that will be using the signer. While we do not have IAC (Infrastructure as Code) for this, you can follow the steps below to setup the KMS key and the user. + +**Note**: If you already have an IAM user you can skip to the [Create a KMS Key](#create-a-kms-key) section. If you have a custom IAM setup/role skip this and assign the permissions to the user or role you want to use. + +### Create an IAM User + +1. Sign in to the AWS Management Console and open the IAM console at https://console.aws.amazon.com/iam. +![IAM Dashboard](img/iam-dash.png) + +2. Click on `Users` in the left-hand menu and then click on `Add user`. + +![Create User](img/kms-user.png) + +3. Leave Permissions empty and click `Next` + +![img.png](img/perms.png) + +4. Add tags if you want and click `Create User` + +![IAM Preview User](img/iam-preview-user.png) + +5. The user will be create and appear in the list of users. Click on the user to view the user details. + +![User List](img/user-list.png) + +6. Click on 'Create access key'. + +
+ Important Note +

+In the example above, we use access keys & secrets to authenticate the user. This is not recommended for production use. There are a lot of ways to authenticate users in AWS and the "Best Practices & alternatives" page below will tell you the best way to authenticate. Since we're only covering access key & secret, we'll ignore these other methods. The AWS documentation is very good and you can find more information on the best practices & alternatives [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html). +

+
+ + +7. Skip the description page + +![user-perms.png](img/user-perms.png) + +8. Click on `Create access key` + +![Create Access Key](img/create-acces-key.png) + +Note down the `Access key ID` and `Secret access key` as you will need these to configure the signer. + +### Create a KMS Key +1. Sign in to the AWS Management Console and open the KMS console at https://console.aws.amazon.com/kms. + +![KMS Key](img/kms-1.png) + +2. Choose `Create key` and fill in the following options: + +![Create Key](img/kms-2.png) + +- Key Type: `Asymmetric`: Since ethereum uses [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) keys, we need to use an asymmetric key. +- Key Usage: `Sign and verify`: We will be using the key to sign transactions so we select this option. +- Key Spec: `ECC_SECG_P256K1`: Ethereum uses the [`secp256k1`](https://en.bitcoin.it/wiki/Secp256k1) curve for transacting keys. + +Note: The advanced options are not required for this setup. You can leave them as default: + +![Advanced Options](img/kms-advanced.png) + +3. Choose `Next` and fill in the following options: + +![KMS Creation Step 2](img/kms-labels.png) + +- Alias: This is an alias that will be used to reference the key in the signer. The field is required but the value doesn't matter. +- Description: This is a description that will be used to describe the key in the signer. This is only optional and only for your reference. +- Tags: These are tags that will be used to describe the key in the signer. These are optional and only for your reference. + +4. Choose `Next` and define your key admin permissions. These are *not* required by the signer itself but are required to manage the key. You can use whatever you like here. + +![KMS Permissions](img/kms-permissons.png) + +5. Choose `Next` and define your user permissions. Here you should set your user as a user. + +![KMS User Permissions](img/kms-user-permissions.png) + +6. Choose `Next` and review your key settings. If everything looks good, choose `Finish`. + +![Review](img/review.png) + +7. Your key will be created and you will be redirected to the key details page. Note down the `Key ID` as you will need this to configure the signer. + +8. You will be redirected to the key details page. Click on the key alias to view the key details. + +![Key Details](img/key-details.png) + +9. Using Your Key (AWS) + +Now that you have your key and user setup, you can use the key to sign transactions. Since the `signerconfig` is used across multiple services, I'll be doing a generic example that just prints out the key. + +Note: this is a very basic example and you should not use this in production. You should store your key in a secure location and use it securely. + + +`signer.yml`: +```yaml +signer_config: + type: "aws" + file: "/path/to/aws.yaml" +``` + +`aws.yaml`: +```yaml +region: us-east-1 +access_key: YOUR_ACCESS_KEY +access_secret: YOUR_ACCESS_SECRET +key_id: f15fa759-7c13-44eb-a868-e7388aa1387b # this will be the id from above. +``` + +This is obviously used in multiple services, so we've put together an example service that will print out the address of your key. + +You can run this locally by running: + +```bash +brew install go # if on mac +git clone https://github.com/synapsecns/sanguine --recurse-submodules +cd sanguine/ethergo/examples/signer +go run main.go --config=/path/to/signer.yml +``` + +We also have this available as a docker container for your convenience here: + +`ghcr.io/synapsecns/sanguine/signer-example:latest` + +## Setup with GCP CloudKMS + +This section is still in progress, please see [here](https://pkg.go.dev/github.com/synapsecns/sanguine/ethergo@v0.9.0/signer/signer#section-readme) for details. + +## Setup with a Local Signer + This section is still in progress, please see [here](https://pkg.go.dev/github.com/synapsecns/sanguine/ethergo@v0.9.0/signer/signer#section-readme) for details. diff --git a/docs/bridge/docs/Services/img/create-acces-key.png b/docs/bridge/docs/Services/img/create-acces-key.png new file mode 100644 index 0000000000..ba7754950d Binary files /dev/null and b/docs/bridge/docs/Services/img/create-acces-key.png differ diff --git a/docs/bridge/docs/Services/img/create-access-key.png b/docs/bridge/docs/Services/img/create-access-key.png new file mode 100644 index 0000000000..f4cc9144fb Binary files /dev/null and b/docs/bridge/docs/Services/img/create-access-key.png differ diff --git a/docs/bridge/docs/Services/img/iam-dash.png b/docs/bridge/docs/Services/img/iam-dash.png new file mode 100644 index 0000000000..63e5244286 Binary files /dev/null and b/docs/bridge/docs/Services/img/iam-dash.png differ diff --git a/docs/bridge/docs/Services/img/iam-preview-user.png b/docs/bridge/docs/Services/img/iam-preview-user.png new file mode 100644 index 0000000000..4ab2183357 Binary files /dev/null and b/docs/bridge/docs/Services/img/iam-preview-user.png differ diff --git a/docs/bridge/docs/Services/img/key-details.png b/docs/bridge/docs/Services/img/key-details.png new file mode 100644 index 0000000000..8e76871998 Binary files /dev/null and b/docs/bridge/docs/Services/img/key-details.png differ diff --git a/docs/bridge/docs/Services/img/kms-1.png b/docs/bridge/docs/Services/img/kms-1.png new file mode 100644 index 0000000000..542887787f Binary files /dev/null and b/docs/bridge/docs/Services/img/kms-1.png differ diff --git a/docs/bridge/docs/Services/img/kms-2.png b/docs/bridge/docs/Services/img/kms-2.png new file mode 100644 index 0000000000..7944a8bf05 Binary files /dev/null and b/docs/bridge/docs/Services/img/kms-2.png differ diff --git a/docs/bridge/docs/Services/img/kms-advanced.png b/docs/bridge/docs/Services/img/kms-advanced.png new file mode 100644 index 0000000000..ec963d87a7 Binary files /dev/null and b/docs/bridge/docs/Services/img/kms-advanced.png differ diff --git a/docs/bridge/docs/Services/img/kms-labels.png b/docs/bridge/docs/Services/img/kms-labels.png new file mode 100644 index 0000000000..5ea8b503ef Binary files /dev/null and b/docs/bridge/docs/Services/img/kms-labels.png differ diff --git a/docs/bridge/docs/Services/img/kms-permissons.png b/docs/bridge/docs/Services/img/kms-permissons.png new file mode 100644 index 0000000000..350aec1a42 Binary files /dev/null and b/docs/bridge/docs/Services/img/kms-permissons.png differ diff --git a/docs/bridge/docs/Services/img/kms-user-permissions.png b/docs/bridge/docs/Services/img/kms-user-permissions.png new file mode 100644 index 0000000000..6518b3531a Binary files /dev/null and b/docs/bridge/docs/Services/img/kms-user-permissions.png differ diff --git a/docs/bridge/docs/Services/img/kms-user.png b/docs/bridge/docs/Services/img/kms-user.png new file mode 100644 index 0000000000..e64369d722 Binary files /dev/null and b/docs/bridge/docs/Services/img/kms-user.png differ diff --git a/docs/bridge/docs/Services/img/perms.png b/docs/bridge/docs/Services/img/perms.png new file mode 100644 index 0000000000..9396d92bed Binary files /dev/null and b/docs/bridge/docs/Services/img/perms.png differ diff --git a/docs/bridge/docs/Services/img/review.png b/docs/bridge/docs/Services/img/review.png new file mode 100644 index 0000000000..21049856fe Binary files /dev/null and b/docs/bridge/docs/Services/img/review.png differ diff --git a/docs/bridge/docs/Services/img/user-list.png b/docs/bridge/docs/Services/img/user-list.png new file mode 100644 index 0000000000..180071ec6b Binary files /dev/null and b/docs/bridge/docs/Services/img/user-list.png differ diff --git a/docs/bridge/docs/Services/img/user-perms.png b/docs/bridge/docs/Services/img/user-perms.png new file mode 100644 index 0000000000..ca133aa275 Binary files /dev/null and b/docs/bridge/docs/Services/img/user-perms.png differ diff --git a/ethergo/.goreleaser.yml b/ethergo/.goreleaser.yml index 6e7dc9ea5f..984e592e77 100644 --- a/ethergo/.goreleaser.yml +++ b/ethergo/.goreleaser.yml @@ -5,7 +5,46 @@ monorepo: dir: ethergo/ builds: - - skip: true + # Linux AMD64 + - id: signer-example + binary: api + ldflags: + # We need to build a static binary because we are building in a glibc based system and running in a musl container + - -s -w -extldflags '-static' + # required workaround for https://github.com/Shopify/sarama/issues/2206 + # See: https://github.com/golang/go/issues/35067#issuecomment-544805311 because we're statically compiling, + # without forcing netgo, we use the cgo resolver which will not work for .local (a canonical tld in kubernetes) + # the other way to resolve this would be to modify the nsswitch.conf in the container, but that's a bit less clean. + # osusergo was included as a recommendation here: https://github.com/kubernetes/kubernetes/pull/114225#issuecomment-1348920040 + tags: + - netgo + - osusergo + env: + - CC=gcc + - CXX=g++ + main: examples/signer-example/main.go + goos: + - linux + goarch: + - amd64 + +dockers: + # Docker AMD64 + - goos: linux + goarch: amd64 + image_templates: + - 'ghcr.io/synapsecns/sanguine/signer-example:latest' + - 'ghcr.io/synapsecns/sanguine/signer-example:{{ .FullCommit }}' + - 'ghcr.io/synapsecns/sanguine/signer-example:{{ .Tag }}' + build_flag_templates: + - '--label=org.opencontainers.image.created={{.Date}}' + - '--label=org.opencontainers.image.name={{.ProjectName}}' + - '--label=org.opencontainers.image.revision={{.FullCommit}}' + - '--label=org.opencontainers.image.version={{.Version}}' + - '--label=org.opencontainers.image.source={{.GitURL}}' + dockerfile: ../docker/signer-example.Dockerfile + ids: + - signer-example # add a source archive at release time source: diff --git a/ethergo/README.md b/ethergo/README.md index 02cfa8a70b..1545e86832 100644 --- a/ethergo/README.md +++ b/ethergo/README.md @@ -16,7 +16,7 @@ Some key components of Ethergo include: - **Manager**: The manager is responsible for handling contract deployments. - **Signer**: Ethergo offers signing and transaction submission utilities, with various adapters for signing transactions and handling race conditions with nonces. It also includes a wallet interface capable of importing keys from seed phrases, private keys, and mnemonics. - To see a working example of Ethergo in action, refer to the [`example`](./example) folder, which provides a complete demonstration of how to use the deployer and manager components. Please note that the APIs are subject to change. + To see a working example of Ethergo in action, refer to the [`example`](./examples) folder, which provides a complete demonstration of how to use the deployer and manager components. Please note that the APIs are subject to change. ## Directory Structure @@ -36,7 +36,7 @@ root │ ├── watcher: Client interface for chain watcher. ├── contracts: Contains interfaces for using contracts with the deployer + manager ├── client: Contains an open tracing compatible ethclient with batching. -├── example: Contains a full featured example of how to use deployer + manager +├── examples: Contains a full featured example of how to use deployer + manager & a signer. ├── forker: Allows the use of fork tests in live chains without docker using an anvil binary. ├── listener: Drop-in contract listener ├── manager: Manages contract deployments. diff --git a/ethergo/backends/anvil/suite_test.go b/ethergo/backends/anvil/suite_test.go index 11ba05f869..57df4304e9 100644 --- a/ethergo/backends/anvil/suite_test.go +++ b/ethergo/backends/anvil/suite_test.go @@ -1,6 +1,8 @@ package anvil_test import ( + "github.com/synapsecns/sanguine/ethergo/examples/contracttests" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" "testing" "github.com/ethereum/go-ethereum/common" @@ -9,8 +11,6 @@ import ( "github.com/synapsecns/sanguine/core" "github.com/synapsecns/sanguine/core/testsuite" "github.com/synapsecns/sanguine/ethergo/backends/anvil" - "github.com/synapsecns/sanguine/ethergo/example" - "github.com/synapsecns/sanguine/ethergo/example/counter" "github.com/synapsecns/sanguine/ethergo/manager" ) @@ -49,8 +49,8 @@ func (a *AnvilSuite) SetupSuite() { a.client, err = anvil.Dial(a.GetSuiteContext(), a.backend.RPCAddress()) Nil(a.T(), err) - deployer := manager.NewDeployerManager(a.T(), example.NewCounterDeployer) - deployedContract := deployer.Get(a.GetSuiteContext(), a.backend, example.CounterType) + deployer := manager.NewDeployerManager(a.T(), contracttests.NewCounterDeployer) + deployedContract := deployer.Get(a.GetSuiteContext(), a.backend, contracttests.CounterType) var ok bool a.counter, ok = deployedContract.ContractHandle().(*counter.CounterRef) diff --git a/ethergo/deployer/deployed_contract_test.go b/ethergo/deployer/deployed_contract_test.go index 04d55b6c7d..7042c3432b 100644 --- a/ethergo/deployer/deployed_contract_test.go +++ b/ethergo/deployer/deployed_contract_test.go @@ -4,7 +4,7 @@ import ( . "github.com/stretchr/testify/assert" "github.com/synapsecns/sanguine/ethergo/backends/simulated" "github.com/synapsecns/sanguine/ethergo/deployer" - "github.com/synapsecns/sanguine/ethergo/example/counter" + counter2 "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" "math/big" ) @@ -13,10 +13,10 @@ func (d *DeployerSuite) TestNewDeployedContract() { backend := simulated.NewSimulatedBackendWithChainID(d.GetTestContext(), d.T(), big.NewInt(chainID)) counterDeployer := backend.GetTxContext(d.GetTestContext(), nil) - deploymentAddress, tx, _, err := counter.DeployCounter(counterDeployer.TransactOpts, backend) + deploymentAddress, tx, _, err := counter2.DeployCounter(counterDeployer.TransactOpts, backend) Nil(d.T(), err) - handle, err := counter.NewCounterRef(deploymentAddress, backend) + handle, err := counter2.NewCounterRef(deploymentAddress, backend) Nil(d.T(), err) deployed, err := deployer.NewDeployedContract(handle, tx) diff --git a/ethergo/example/README.md b/ethergo/examples/contracttests/README.md similarity index 98% rename from ethergo/example/README.md rename to ethergo/examples/contracttests/README.md index 6ad31612ee..f8a3261b1b 100644 --- a/ethergo/example/README.md +++ b/ethergo/examples/contracttests/README.md @@ -153,8 +153,8 @@ "context" "github.com/ethereum/go-ethereum/accounts/abi/bind" . "github.com/stretchr/testify/assert" - "github.com/synapsecns/sanguine/ethergo/example" - "github.com/synapsecns/sanguine/ethergo/example/counter" + "github.com/synapsecns/sanguine/ethergo/examples" + "github.com/synapsecns/sanguine/ethergo/examples/counter" "github.com/synapsecns/sanguine/ethergo/manager" "github.com/synapsecns/sanguine/ethergo/backends/simulated" "testing" @@ -233,7 +233,7 @@ "context" "github.com/synapsecns/sanguine/ethergo/backends" "github.com/synapsecns/sanguine/ethergo/contracts" - "github.com/synapsecns/sanguine/ethergo/example/counter" + "github.com/synapsecns/sanguine/ethergo/examples/counter" "github.com/synapsecns/sanguine/ethergo/manager" "testing" ) @@ -255,7 +255,7 @@ "context" "github.com/synapsecns/sanguine/ethergo/backends" "github.com/synapsecns/sanguine/ethergo/contracts" - "github.com/synapsecns/sanguine/ethergo/example" + "github.com/synapsecns/sanguine/ethergo/examples" "github.com/synapsecns/sanguine/ethergo/manager" "testing" ) diff --git a/ethergo/example/contracttype.go b/ethergo/examples/contracttests/contracttype.go similarity index 95% rename from ethergo/example/contracttype.go rename to ethergo/examples/contracttests/contracttype.go index 43f2f9b0fa..06f4b1685c 100644 --- a/ethergo/example/contracttype.go +++ b/ethergo/examples/contracttests/contracttype.go @@ -1,9 +1,9 @@ -package example +package contracttests import ( "github.com/ethereum/go-ethereum/common/compiler" "github.com/synapsecns/sanguine/ethergo/contracts" - "github.com/synapsecns/sanguine/ethergo/example/counter" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" ) // set all contact types. diff --git a/ethergo/example/contracttypeimpl_string.go b/ethergo/examples/contracttests/contracttypeimpl_string.go similarity index 96% rename from ethergo/example/contracttypeimpl_string.go rename to ethergo/examples/contracttests/contracttypeimpl_string.go index 6f15257e8f..cb53e0a008 100644 --- a/ethergo/example/contracttypeimpl_string.go +++ b/ethergo/examples/contracttests/contracttypeimpl_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=contractTypeImpl -linecomment"; DO NOT EDIT. -package example +package contracttests import "strconv" diff --git a/ethergo/example/counter/counter.abigen.go b/ethergo/examples/contracttests/counter/counter.abigen.go similarity index 100% rename from ethergo/example/counter/counter.abigen.go rename to ethergo/examples/contracttests/counter/counter.abigen.go diff --git a/ethergo/example/counter/counter.contractinfo.json b/ethergo/examples/contracttests/counter/counter.contractinfo.json similarity index 100% rename from ethergo/example/counter/counter.contractinfo.json rename to ethergo/examples/contracttests/counter/counter.contractinfo.json diff --git a/ethergo/example/counter/counter.metadata.go b/ethergo/examples/contracttests/counter/counter.metadata.go similarity index 100% rename from ethergo/example/counter/counter.metadata.go rename to ethergo/examples/contracttests/counter/counter.metadata.go diff --git a/ethergo/example/counter/counter.sol b/ethergo/examples/contracttests/counter/counter.sol similarity index 100% rename from ethergo/example/counter/counter.sol rename to ethergo/examples/contracttests/counter/counter.sol diff --git a/ethergo/example/counter/generate.go b/ethergo/examples/contracttests/counter/generate.go similarity index 100% rename from ethergo/example/counter/generate.go rename to ethergo/examples/contracttests/counter/generate.go diff --git a/ethergo/example/counter/helpers.go b/ethergo/examples/contracttests/counter/helpers.go similarity index 100% rename from ethergo/example/counter/helpers.go rename to ethergo/examples/contracttests/counter/helpers.go diff --git a/ethergo/example/counter_test.go b/ethergo/examples/contracttests/counter_test.go similarity index 80% rename from ethergo/example/counter_test.go rename to ethergo/examples/contracttests/counter_test.go index 93b4dc14ab..d677d816e2 100644 --- a/ethergo/example/counter_test.go +++ b/ethergo/examples/contracttests/counter_test.go @@ -1,12 +1,12 @@ -package example_test +package contracttests_test import ( "context" "github.com/ethereum/go-ethereum/accounts/abi/bind" . "github.com/stretchr/testify/assert" "github.com/synapsecns/sanguine/ethergo/backends/simulated" - "github.com/synapsecns/sanguine/ethergo/example" - "github.com/synapsecns/sanguine/ethergo/example/counter" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" "github.com/synapsecns/sanguine/ethergo/manager" "testing" "time" @@ -19,11 +19,11 @@ func TestCounter(t *testing.T) { // since extra deployers don't necessarily deploy anything (only when requested in the GetOnlyContractRegistry) // adding them here won't slow anything down. It's recommended you have a global slice of these deployers you register every time. - deployer := manager.NewDeployerManager(t, example.NewCounterDeployer) + deployer := manager.NewDeployerManager(t, contracttests.NewCounterDeployer) newTestBackend := simulated.NewSimulatedBackend(testContext, t) - deployedContract := deployer.Get(testContext, newTestBackend, example.CounterType) + deployedContract := deployer.Get(testContext, newTestBackend, contracttests.CounterType) // if you're using these often, it's recommended you extend manager and add type casted getters here, along with the global registry //nolint: forcetypeassert counterHandle := deployedContract.ContractHandle().(*counter.CounterRef) @@ -48,6 +48,6 @@ func TestCounter(t *testing.T) { func TestDependenciesCorrect(t *testing.T) { manager.AssertDependenciesCorrect(context.Background(), t, func() manager.IDeployManager { - return manager.NewDeployerManager(t, example.NewCounterDeployer) + return manager.NewDeployerManager(t, contracttests.NewCounterDeployer) }) } diff --git a/ethergo/example/deployer.go b/ethergo/examples/contracttests/deployer.go similarity index 86% rename from ethergo/example/deployer.go rename to ethergo/examples/contracttests/deployer.go index bce378114b..4fe4542d34 100644 --- a/ethergo/example/deployer.go +++ b/ethergo/examples/contracttests/deployer.go @@ -1,4 +1,4 @@ -package example +package contracttests import ( "context" @@ -8,7 +8,7 @@ import ( "github.com/synapsecns/sanguine/ethergo/backends" "github.com/synapsecns/sanguine/ethergo/contracts" "github.com/synapsecns/sanguine/ethergo/deployer" - "github.com/synapsecns/sanguine/ethergo/example/counter" + counter2 "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" ) // CounterDeployer deploys a counter. @@ -28,11 +28,11 @@ func (n *CounterDeployer) Deploy(ctx context.Context) (contracts.DeployedContrac //nolint: wrapcheck return n.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error) { //nolint: wrapcheck - return counter.DeployCounter(transactOps, backend) + return counter2.DeployCounter(transactOps, backend) }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) { // this is kept separate because we often want to add an address handle to this so it's compatible with vm.ContractRef //nolint: wrapcheck - return counter.NewCounterRef(address, backend) + return counter2.NewCounterRef(address, backend) }) } diff --git a/ethergo/example/deploymanager.go b/ethergo/examples/contracttests/deploymanager.go similarity index 90% rename from ethergo/example/deploymanager.go rename to ethergo/examples/contracttests/deploymanager.go index 8f86031b7d..b6ac1a1c3b 100644 --- a/ethergo/example/deploymanager.go +++ b/ethergo/examples/contracttests/deploymanager.go @@ -1,10 +1,10 @@ -package example +package contracttests import ( "context" "github.com/synapsecns/sanguine/ethergo/backends" "github.com/synapsecns/sanguine/ethergo/contracts" - "github.com/synapsecns/sanguine/ethergo/example/counter" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" "github.com/synapsecns/sanguine/ethergo/manager" "testing" ) diff --git a/ethergo/example/doc.go b/ethergo/examples/contracttests/doc.go similarity index 74% rename from ethergo/example/doc.go rename to ethergo/examples/contracttests/doc.go index d8c6eecb56..360cebb639 100644 --- a/ethergo/example/doc.go +++ b/ethergo/examples/contracttests/doc.go @@ -1,2 +1,2 @@ // Package example defines an example project that uses ethergo -package example +package contracttests diff --git a/ethergo/examples/signer-example/README.md b/ethergo/examples/signer-example/README.md new file mode 100644 index 0000000000..8c1fb2ac1d --- /dev/null +++ b/ethergo/examples/signer-example/README.md @@ -0,0 +1,3 @@ +# Signer Config Example + +The signer config example is a simple signer example for the docs that reads a signer config and prints the address of a key. diff --git a/ethergo/examples/signer-example/cmd/cmd.go b/ethergo/examples/signer-example/cmd/cmd.go new file mode 100644 index 0000000000..967646c335 --- /dev/null +++ b/ethergo/examples/signer-example/cmd/cmd.go @@ -0,0 +1,67 @@ +// Package cmd provides the command line interface for the opbot. +package cmd + +import ( + "fmt" + "github.com/synapsecns/sanguine/core/config" + "github.com/synapsecns/sanguine/core/metrics" + exampleConfig "github.com/synapsecns/sanguine/ethergo/examples/signer-example/config" + signerConfig "github.com/synapsecns/sanguine/ethergo/signer/config" + "github.com/urfave/cli/v2" + "gopkg.in/yaml.v3" + "os" +) + +// Start starts the command line tool. +func Start(args []string, buildInfo config.BuildInfo) { + app := cli.NewApp() + app.Name = buildInfo.Name() + + app.Description = buildInfo.VersionString() + "Opbot is a tool to manage operations." + app.Usage = fmt.Sprintf("%s --help", buildInfo.Name()) + app.EnableBashCompletion = true + app.Before = func(c *cli.Context) error { + // nolint:wrapcheck + return metrics.Setup(c.Context, buildInfo) + } + app.Flags = []cli.Flag{fileFlag} + app.Action = action + err := app.Run(args) + + if err != nil { + panic(err) + } +} + +var fileFlag = &cli.StringFlag{ + Name: "config", + Usage: "--config /Users/synapsecns/config.yaml", + Required: true, +} + +var action = func(c *cli.Context) error { + configFile, err := os.ReadFile(c.String(fileFlag.Name)) + if err != nil { + return fmt.Errorf("failed to open config file: %w", err) + } + + var cfg exampleConfig.ExampleConfig + // nolint: musttag + err = yaml.Unmarshal(configFile, &cfg) + if err != nil { + return fmt.Errorf("failed to unmarshal config file: %w", err) + } + + if ok, err := cfg.SignerConfig.IsValid(c.Context); !ok { + panic(fmt.Errorf("failed to validate signer config: %w", err)) + } + + signer, err := signerConfig.SignerFromConfig(c.Context, cfg.SignerConfig) + if err != nil { + return fmt.Errorf("could not create signer: %w", err) + } + + fmt.Printf("signer address is %s", signer.Address()) + + return nil +} diff --git a/ethergo/examples/signer-example/config/config.go b/ethergo/examples/signer-example/config/config.go new file mode 100644 index 0000000000..aeb36554cf --- /dev/null +++ b/ethergo/examples/signer-example/config/config.go @@ -0,0 +1,9 @@ +// Package config provides configuration for the example signer. +package config + +import "github.com/synapsecns/sanguine/ethergo/signer/config" + +// ExampleConfig is a configuration for the example signer. +type ExampleConfig struct { + config.SignerConfig `yaml:"signer_config"` +} diff --git a/ethergo/examples/signer-example/main.go b/ethergo/examples/signer-example/main.go new file mode 100644 index 0000000000..7443fd7f94 --- /dev/null +++ b/ethergo/examples/signer-example/main.go @@ -0,0 +1,12 @@ +// Package main provides the command line interface for the example signer. +package main + +import ( + "github.com/synapsecns/sanguine/ethergo/examples/signer-example/cmd" + "github.com/synapsecns/sanguine/ethergo/examples/signer-example/metadata" + "os" +) + +func main() { + cmd.Start(os.Args, metadata.BuildInfo()) +} diff --git a/ethergo/examples/signer-example/metadata/metadata.go b/ethergo/examples/signer-example/metadata/metadata.go new file mode 100644 index 0000000000..949538d904 --- /dev/null +++ b/ethergo/examples/signer-example/metadata/metadata.go @@ -0,0 +1,15 @@ +// Package metadata provides a metadata service for the example signer. +package metadata + +import "github.com/synapsecns/sanguine/core/config" + +var ( + version = config.DefaultVersion + commit = config.DefaultCommit + date = config.DefaultDate +) + +// BuildInfo returns the build info for the service. +func BuildInfo() config.BuildInfo { + return config.NewBuildInfo(version, commit, "signer-aws-example", date) +} diff --git a/ethergo/forker/fork_test.go b/ethergo/forker/fork_test.go index bcd3ff3a27..6301aad0d8 100644 --- a/ethergo/forker/fork_test.go +++ b/ethergo/forker/fork_test.go @@ -5,8 +5,8 @@ import ( "github.com/ethereum/go-ethereum/ethclient" . "github.com/stretchr/testify/assert" "github.com/synapsecns/sanguine/ethergo/backends/geth" - "github.com/synapsecns/sanguine/ethergo/example" - "github.com/synapsecns/sanguine/ethergo/example/counter" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" "github.com/synapsecns/sanguine/ethergo/forker" "github.com/synapsecns/sanguine/ethergo/manager" ) @@ -18,8 +18,8 @@ func (f *ForkSuite) TestFork() { err := forker.Fork(testContext, backend.HTTPEndpoint(), 10, func(client *ethclient.Client) { // deploy the counter contract - deployer := manager.NewDeployerManager(f.T(), example.NewCounterDeployer) - deployedContract := deployer.Get(testContext, backend, example.CounterType) + deployer := manager.NewDeployerManager(f.T(), contracttests.NewCounterDeployer) + deployedContract := deployer.Get(testContext, backend, contracttests.CounterType) // if you're using these often, it's recommended you extend manager and add type casted getters here, along with the global registry //nolint: forcetypeassert counterHandle := deployedContract.ContractHandle().(*counter.CounterRef) diff --git a/ethergo/go.mod b/ethergo/go.mod index 104d4dacc2..a603d4dd08 100644 --- a/ethergo/go.mod +++ b/ethergo/go.mod @@ -54,6 +54,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/teivah/onecontext v1.3.0 github.com/tyler-smith/go-bip39 v1.1.0 + github.com/urfave/cli/v2 v2.27.2 github.com/viant/toolbox v0.24.0 go.opentelemetry.io/otel v1.27.0 go.opentelemetry.io/otel/metric v1.27.0 @@ -67,6 +68,7 @@ require ( google.golang.org/api v0.183.0 google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.5.6 gorm.io/driver/sqlite v1.5.6 gorm.io/gorm v1.25.10 @@ -248,7 +250,6 @@ require ( github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.1 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.3.1 // indirect github.com/uptrace/opentelemetry-go-extra/otelzap v0.3.1 // indirect - github.com/urfave/cli/v2 v2.27.2 // indirect github.com/valyala/fastjson v1.6.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -284,7 +285,6 @@ require ( google.golang.org/grpc v1.64.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/ethergo/listener/suite_test.go b/ethergo/listener/suite_test.go index de38f6594e..2245941e11 100644 --- a/ethergo/listener/suite_test.go +++ b/ethergo/listener/suite_test.go @@ -6,8 +6,8 @@ import ( "github.com/brianvoe/gofakeit/v6" "github.com/ipfs/go-log" common_base "github.com/synapsecns/sanguine/core/dbcommon" - "github.com/synapsecns/sanguine/ethergo/example" - "github.com/synapsecns/sanguine/ethergo/example/counter" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" "github.com/synapsecns/sanguine/ethergo/listener" db2 "github.com/synapsecns/sanguine/ethergo/listener/db" "gorm.io/gorm" @@ -31,7 +31,7 @@ const chainID = 10 type ListenerTestSuite struct { *testsuite.TestSuite - manager *example.DeployManager + manager *contracttests.DeployManager backend backends.SimulatedTestBackend store db2.ChainListenerDB metrics metrics.Handler @@ -53,7 +53,7 @@ func TestListenerSuite(t *testing.T) { func (l *ListenerTestSuite) SetupTest() { l.TestSuite.SetupTest() - l.manager = example.NewDeployManager(l.T()) + l.manager = contracttests.NewDeployManager(l.T()) l.backend = geth.NewEmbeddedBackendForChainID(l.GetTestContext(), l.T(), big.NewInt(chainID)) var err error l.metrics = metrics.NewNullHandler() diff --git a/ethergo/signer/config/signer.go b/ethergo/signer/config/signer.go index 436bd2f147..525db76b47 100644 --- a/ethergo/signer/config/signer.go +++ b/ethergo/signer/config/signer.go @@ -17,6 +17,7 @@ import ( "gopkg.in/yaml.v2" "os" "path/filepath" + "slices" "strings" ) @@ -32,15 +33,19 @@ type SignerConfig struct { // IsValid determines if the config is valid. func (s SignerConfig) IsValid(_ context.Context) (ok bool, err error) { - if !strings.EqualFold(s.Type, FileType.String()) { + if !slices.ContainsFunc(AllSignerTypes, func(signerType SignerType) bool { + return strings.EqualFold(signerType.String(), s.Type) + }) { return false, fmt.Errorf("%w: %s. must be one of: %s", ErrUnsupportedSignerType, s.Type, allSignerTypesList()) } - // TODO: we'll need to switch validity here based on type once we have more then one supported configuration type - // alternatively, we could try to use an awsconfig type file, but this makes the virtual box setup more tedious. A third option is a json blob - _, err = wallet.FromKeyFile(s.File) - if err != nil { - return false, fmt.Errorf("file %s invalid: %w", s.File, err) + if strings.EqualFold(s.Type, FileType.String()) { + // TODO: we'll need to switch validity here based on type once we have more then one supported configuration type + // alternatively, we could try to use an awsconfig type file, but this makes the virtual box setup more tedious. A third option is a json blob + _, err = wallet.FromKeyFile(s.File) + if err != nil { + return false, fmt.Errorf("file %s invalid: %w", s.File, err) + } } return true, nil @@ -63,6 +68,11 @@ const ( GCPType // GCP ) +// lString returns the lowercase string of the signer type. +func (s SignerType) lString() string { + return strings.ToLower(s.String()) +} + // AllSignerTypes is a list of all contract types. Since we use stringer and this is a testing library, instead // of manually copying all these out we pull the names out of stringer. In order to make sure stringer is updated, we panic on // any method called where the index is higher than the stringer array length. @@ -90,8 +100,8 @@ func allSignerTypesList() string { // TODO: this needs to be moved to some kind of common package. // in the old code configs were split into responsible packages. Maybe something like that works here? func SignerFromConfig(ctx context.Context, config SignerConfig) (signer.Signer, error) { - switch config.Type { - case FileType.String(): + switch strings.ToLower(config.Type) { + case FileType.lString(): wall, err := wallet.FromKeyFile(core.ExpandOrReturnPath(config.File)) if err != nil { return nil, fmt.Errorf("could not add signer: %w", err) @@ -100,7 +110,7 @@ func SignerFromConfig(ctx context.Context, config SignerConfig) (signer.Signer, res := localsigner.NewSigner(wall.PrivateKey()) return res, nil - case AWSType.String(): + case AWSType.lString(): awsConfig, err := DecodeAWSConfig(config.File) if err != nil { return nil, fmt.Errorf("could not decode aws config: %w", err) @@ -110,7 +120,7 @@ func SignerFromConfig(ctx context.Context, config SignerConfig) (signer.Signer, return nil, fmt.Errorf("could not decode aws config: %w", err) } return res, nil - case GCPType.String(): + case GCPType.lString(): gcpConfig, err := DecodeGCPConfig(config.File) if err != nil { return nil, fmt.Errorf("could not decode gcp config: %w", err) diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index 2c19b33347..7ea7512de6 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -2,6 +2,8 @@ package submitter_test import ( "fmt" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests/counter" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -10,8 +12,6 @@ import ( "github.com/stretchr/testify/mock" "github.com/synapsecns/sanguine/core/testsuite" clientMocks "github.com/synapsecns/sanguine/ethergo/client/mocks" - "github.com/synapsecns/sanguine/ethergo/example" - "github.com/synapsecns/sanguine/ethergo/example/counter" "github.com/synapsecns/sanguine/ethergo/manager" ethMocks "github.com/synapsecns/sanguine/ethergo/mocks" "github.com/synapsecns/sanguine/ethergo/signer/signer/localsigner" @@ -270,7 +270,7 @@ func (s *SubmitterSuite) TestGetNonce() { func (s *SubmitterSuite) TestSubmitTransaction() { _, cntr := manager.GetContract[*counter.CounterRef](s.GetTestContext(), s.T(), - s.deployer, s.testBackends[0], example.CounterType) + s.deployer, s.testBackends[0], contracttests.CounterType) cfg := &config.Config{} chainID := s.testBackends[0].GetBigChainID() diff --git a/ethergo/submitter/suite_test.go b/ethergo/submitter/suite_test.go index d49f25ba8a..b590353428 100644 --- a/ethergo/submitter/suite_test.go +++ b/ethergo/submitter/suite_test.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "github.com/synapsecns/sanguine/ethergo/examples/contracttests" "math/big" "os" "sync" @@ -24,7 +25,6 @@ import ( "github.com/synapsecns/sanguine/ethergo/backends/anvil" "github.com/synapsecns/sanguine/ethergo/backends/simulated" "github.com/synapsecns/sanguine/ethergo/client" - "github.com/synapsecns/sanguine/ethergo/example" "github.com/synapsecns/sanguine/ethergo/manager" "github.com/synapsecns/sanguine/ethergo/mocks" "github.com/synapsecns/sanguine/ethergo/signer/nonce" @@ -80,7 +80,7 @@ func (s *SubmitterSuite) SetupSuite() { testChainIDs := []uint64{1, 3, 4} s.testBackends = make([]backends.SimulatedTestBackend, len(testChainIDs)) - s.deployer = manager.NewDeployerManager(s.T(), example.NewCounterDeployer) + s.deployer = manager.NewDeployerManager(s.T(), contracttests.NewCounterDeployer) var wg sync.WaitGroup // wait for all the backends to be created, add 1 to the wait group for the metrics @@ -115,7 +115,7 @@ func (s *SubmitterSuite) SetupSuite() { options.SetProcessLogOptions(processlog.WithLogFileName(fmt.Sprintf("chain-%d.log", chainID)), processlog.WithLogDir(logDir)) s.testBackends[index] = anvil.NewAnvilBackend(s.GetSuiteContext(), s.T(), options) - s.deployer.Get(s.GetSuiteContext(), s.testBackends[index], example.CounterType) + s.deployer.Get(s.GetSuiteContext(), s.testBackends[index], contracttests.CounterType) }(i, chainID) } wg.Wait()