diff --git a/covenant-signer/Dockerfile b/covenant-signer/Dockerfile index f5c4c6a..54c9f28 100644 --- a/covenant-signer/Dockerfile +++ b/covenant-signer/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22.3-alpine as builder +FROM golang:1.23.1-alpine as builder # Version to build. Default is the Git HEAD. ARG VERSION="HEAD" diff --git a/covenant-signer/config/config.go b/covenant-signer/config/config.go index f3fe5f3..07d3104 100644 --- a/covenant-signer/config/config.go +++ b/covenant-signer/config/config.go @@ -42,13 +42,11 @@ func (cfg *Config) Parse() (*ParsedConfig, error) { } serverConfig, err := cfg.Server.Parse() - if err != nil { return nil, err } metricsConfig, err := cfg.Metrics.Parse() - if err != nil { return nil, err } diff --git a/covenant-signer/go.mod b/covenant-signer/go.mod index 176d18e..d92a81b 100644 --- a/covenant-signer/go.mod +++ b/covenant-signer/go.mod @@ -1,8 +1,6 @@ module github.com/babylonlabs-io/covenant-emulator/covenant-signer -go 1.22.3 - -toolchain go1.22.4 +go 1.23.1 require ( github.com/btcsuite/btcd v0.24.2 diff --git a/covenant-signer/itest/bitcoind_node_setup.go b/covenant-signer/itest/bitcoindnodesetup.go similarity index 100% rename from covenant-signer/itest/bitcoind_node_setup.go rename to covenant-signer/itest/bitcoindnodesetup.go diff --git a/covenant-signer/itest/containers/config.go b/covenant-signer/itest/containers/config.go index c93dbd0..0713d45 100644 --- a/covenant-signer/itest/containers/config.go +++ b/covenant-signer/itest/containers/config.go @@ -10,7 +10,7 @@ type ImageConfig struct { //nolint:deadcode const ( dockerBitcoindRepository = "lncm/bitcoind" - dockerBitcoindVersionTag = "v26.0" + dockerBitcoindVersionTag = "v27.0" ) // NewImageConfig returns ImageConfig needed for running e2e test. diff --git a/covenant-signer/itest/containers/containers.go b/covenant-signer/itest/containers/containers.go index 5c09c6c..1281124 100644 --- a/covenant-signer/itest/containers/containers.go +++ b/covenant-signer/itest/containers/containers.go @@ -134,12 +134,12 @@ func (m *Manager) RunBitcoindResource( fmt.Sprintf("%s/:/data/.bitcoin", bitcoindCfgPath), }, ExposedPorts: []string{ - "8332", - "8333", - "28332", - "28333", - "18443", - "18444", + "8332/tcp", + "8333/tcp", + "28332/tcp", + "28333/tcp", + "18443/tcp", + "18444/tcp", }, PortBindings: map[docker.Port][]docker.PortBinding{ "8332/tcp": {{HostIP: "", HostPort: "8332"}}, diff --git a/covenant-signer/itest/e2e_test.go b/covenant-signer/itest/e2etest.go similarity index 54% rename from covenant-signer/itest/e2e_test.go rename to covenant-signer/itest/e2etest.go index cb7b722..39fb952 100644 --- a/covenant-signer/itest/e2e_test.go +++ b/covenant-signer/itest/e2etest.go @@ -22,131 +22,15 @@ import ( "github.com/babylonlabs-io/babylon/testutil/datagen" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/stretchr/testify/require" - "github.com/babylonlabs-io/covenant-emulator/covenant-signer/config" - "github.com/babylonlabs-io/covenant-emulator/covenant-signer/itest/containers" - "github.com/babylonlabs-io/covenant-emulator/covenant-signer/keystore/cosmos" - "github.com/babylonlabs-io/covenant-emulator/covenant-signer/observability/metrics" "github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerapp" "github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerservice" "github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerservice/types" ) -var ( - netParams = &chaincfg.RegressionNetParams - eventuallyPollInterval = 100 * time.Millisecond - eventuallyTimeout = 10 * time.Second -) - -type TestManager struct { - t *testing.T - bitcoindHandler *BitcoindTestHandler - walletPass string - covenantPrivKey *btcec.PrivateKey - signerConfig *config.Config - app *signerapp.SignerApp - server *signerservice.SigningServer -} - -type stakingData struct { - stakingAmount btcutil.Amount - stakingTime uint16 - stakingFeeRate btcutil.Amount -} - -func defaultStakingData() *stakingData { - return &stakingData{ - stakingAmount: btcutil.Amount(100000), - stakingTime: 10000, - stakingFeeRate: btcutil.Amount(5000), // feeRatePerKb - } -} - -func StartManager( - t *testing.T, - numMatureOutputsInWallet uint32) *TestManager { - m, err := containers.NewManager() - require.NoError(t, err) - t.Cleanup(func() { - _ = m.ClearResources() - }) - - h := NewBitcoindHandler(t, m) - h.Start() - - // Give some time to launch and bitcoind - time.Sleep(2 * time.Second) - - passphrase := "pass" - _ = h.CreateWallet("test-wallet", passphrase) - // only outputs which are 100 deep are mature - _ = h.GenerateBlocks(int(numMatureOutputsInWallet) + 100) - - appConfig := config.DefaultConfig() - - appConfig.KeyStore.KeyStoreType = "cosmos" - appConfig.KeyStore.CosmosKeyStore.ChainID = "test-chain" - appConfig.KeyStore.CosmosKeyStore.Passphrase = passphrase - appConfig.KeyStore.CosmosKeyStore.KeyName = "test-key" - appConfig.KeyStore.CosmosKeyStore.KeyDirectory = "" - appConfig.KeyStore.CosmosKeyStore.KeyringBackend = "memory" - - retriever, err := cosmos.NewCosmosKeyringRetriever(appConfig.KeyStore.CosmosKeyStore) - require.NoError(t, err) - - keyInfo, err := retriever.Kr.CreateChainKey( - appConfig.KeyStore.CosmosKeyStore.Passphrase, - "", - ) - require.NoError(t, err) - - app := signerapp.NewSignerApp( - retriever, - ) - - met := metrics.NewCovenantSignerMetrics() - parsedConfig, err := appConfig.Parse() - require.NoError(t, err) - - server, err := signerservice.New( - context.Background(), - parsedConfig, - app, - met, - ) - - require.NoError(t, err) - - go func() { - _ = server.Start() - }() - - // Give some time to launch server - time.Sleep(3 * time.Second) - - t.Cleanup(func() { - _ = server.Stop(context.TODO()) - }) - - return &TestManager{ - t: t, - bitcoindHandler: h, - walletPass: passphrase, - covenantPrivKey: keyInfo.PrivateKey, - signerConfig: appConfig, - app: app, - server: server, - } -} - -func (tm *TestManager) SigningServerUrl() string { - return fmt.Sprintf("http://%s:%d", tm.signerConfig.Server.Host, tm.signerConfig.Server.Port) -} - func buildDataToSign(t *testing.T, covnenantPublicKey *btcec.PublicKey) signerapp.ParsedSigningRequest { stakerPrivKey, err := btcec.NewPrivateKey() require.NoError(t, err) @@ -264,61 +148,6 @@ func TestSigningTransactions(t *testing.T) { require.NoError(t, err) } -func (tm *TestManager) verifyResponse(resp *signerapp.ParsedSigningResponse, req *signerapp.ParsedSigningRequest) error { - - slashAdaptorSig, err := asig.NewAdaptorSignatureFromBytes(resp.SlashAdaptorSigs[0]) - - if err != nil { - return err - } - - err = btcstaking.EncVerifyTransactionSigWithOutput( - req.SlashingTx, - req.StakingTx.TxOut[req.StakingOutputIdx], - req.SlashingScript, - tm.covenantPrivKey.PubKey(), - req.FpEncKeys[0], - slashAdaptorSig, - ) - - if err != nil { - return fmt.Errorf("failed to verify slash adaptor signature for slashing tx: %w", err) - } - - slashUnbondingAdaptorSig, err := asig.NewAdaptorSignatureFromBytes(resp.SlashUnbondingAdaptorSigs[0]) - - if err != nil { - return err - } - - err = btcstaking.EncVerifyTransactionSigWithOutput( - req.SlashUnbondingTx, - req.UnbondingTx.TxOut[0], - req.UnbondingSlashingScript, - tm.covenantPrivKey.PubKey(), - req.FpEncKeys[0], - slashUnbondingAdaptorSig, - ) - - if err != nil { - return fmt.Errorf("failed to verify slash unbonding adaptor signature for slash unbonding tx: %w", err) - } - - err = btcstaking.VerifyTransactionSigWithOutput( - req.UnbondingTx, - req.StakingTx.TxOut[req.StakingOutputIdx], - req.UnbondingScript, - tm.covenantPrivKey.PubKey(), - resp.UnbondingSig.Serialize(), - ) - - if err != nil { - return fmt.Errorf("failed to verify unbonding signature for unbonding tx: %w", err) - } - - return nil -} - func TestRejectToLargeRequest(t *testing.T) { tm := StartManager(t, 100) r := rand.New(rand.NewSource(time.Now().UnixNano())) diff --git a/covenant-signer/itest/testmanager.go b/covenant-signer/itest/testmanager.go new file mode 100644 index 0000000..97a60c8 --- /dev/null +++ b/covenant-signer/itest/testmanager.go @@ -0,0 +1,170 @@ +package e2etest + +import ( + "context" + "fmt" + "testing" + "time" + + asig "github.com/babylonlabs-io/babylon/crypto/schnorr-adaptor-signature" + + "github.com/babylonlabs-io/babylon/btcstaking" + "github.com/babylonlabs-io/covenant-emulator/covenant-signer/config" + "github.com/babylonlabs-io/covenant-emulator/covenant-signer/itest/containers" + "github.com/babylonlabs-io/covenant-emulator/covenant-signer/keystore/cosmos" + "github.com/babylonlabs-io/covenant-emulator/covenant-signer/observability/metrics" + "github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerapp" + "github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerservice" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/chaincfg" + "github.com/stretchr/testify/require" +) + +var ( + netParams = &chaincfg.RegressionNetParams + eventuallyPollInterval = 100 * time.Millisecond + eventuallyTimeout = 10 * time.Second +) + +type TestManager struct { + t *testing.T + bitcoindHandler *BitcoindTestHandler + walletPass string + covenantPrivKey *btcec.PrivateKey + signerConfig *config.Config + app *signerapp.SignerApp + server *signerservice.SigningServer +} + +func StartManager( + t *testing.T, + numMatureOutputsInWallet uint32) *TestManager { + m, err := containers.NewManager() + require.NoError(t, err) + t.Cleanup(func() { + _ = m.ClearResources() + }) + + h := NewBitcoindHandler(t, m) + h.Start() + + passphrase := "pass" + _ = h.CreateWallet("test-wallet", passphrase) + // only outputs which are 100 deep are mature + _ = h.GenerateBlocks(int(numMatureOutputsInWallet) + 100) + + appConfig := config.DefaultConfig() + + appConfig.KeyStore.KeyStoreType = "cosmos" + appConfig.KeyStore.CosmosKeyStore.ChainID = "test-chain" + appConfig.KeyStore.CosmosKeyStore.Passphrase = passphrase + appConfig.KeyStore.CosmosKeyStore.KeyName = "test-key" + appConfig.KeyStore.CosmosKeyStore.KeyDirectory = "" + appConfig.KeyStore.CosmosKeyStore.KeyringBackend = "memory" + + retriever, err := cosmos.NewCosmosKeyringRetriever(appConfig.KeyStore.CosmosKeyStore) + require.NoError(t, err) + + keyInfo, err := retriever.Kr.CreateChainKey( + appConfig.KeyStore.CosmosKeyStore.Passphrase, + "", + ) + require.NoError(t, err) + + app := signerapp.NewSignerApp( + retriever, + ) + + met := metrics.NewCovenantSignerMetrics() + parsedConfig, err := appConfig.Parse() + require.NoError(t, err) + + server, err := signerservice.New( + context.Background(), + parsedConfig, + app, + met, + ) + + require.NoError(t, err) + + go func() { + _ = server.Start() + }() + + // Give some time to launch server + time.Sleep(3 * time.Second) + + t.Cleanup(func() { + _ = server.Stop(context.TODO()) + }) + + return &TestManager{ + t: t, + bitcoindHandler: h, + walletPass: passphrase, + covenantPrivKey: keyInfo.PrivateKey, + signerConfig: appConfig, + app: app, + server: server, + } +} + +func (tm *TestManager) SigningServerUrl() string { + return fmt.Sprintf("http://%s:%d", tm.signerConfig.Server.Host, tm.signerConfig.Server.Port) +} + +func (tm *TestManager) verifyResponse(resp *signerapp.ParsedSigningResponse, req *signerapp.ParsedSigningRequest) error { + + slashAdaptorSig, err := asig.NewAdaptorSignatureFromBytes(resp.SlashAdaptorSigs[0]) + + if err != nil { + return err + } + + err = btcstaking.EncVerifyTransactionSigWithOutput( + req.SlashingTx, + req.StakingTx.TxOut[req.StakingOutputIdx], + req.SlashingScript, + tm.covenantPrivKey.PubKey(), + req.FpEncKeys[0], + slashAdaptorSig, + ) + + if err != nil { + return fmt.Errorf("failed to verify slash adaptor signature for slashing tx: %w", err) + } + + slashUnbondingAdaptorSig, err := asig.NewAdaptorSignatureFromBytes(resp.SlashUnbondingAdaptorSigs[0]) + + if err != nil { + return err + } + + err = btcstaking.EncVerifyTransactionSigWithOutput( + req.SlashUnbondingTx, + req.UnbondingTx.TxOut[0], + req.UnbondingSlashingScript, + tm.covenantPrivKey.PubKey(), + req.FpEncKeys[0], + slashUnbondingAdaptorSig, + ) + + if err != nil { + return fmt.Errorf("failed to verify slash unbonding adaptor signature for slash unbonding tx: %w", err) + } + + err = btcstaking.VerifyTransactionSigWithOutput( + req.UnbondingTx, + req.StakingTx.TxOut[req.StakingOutputIdx], + req.UnbondingScript, + tm.covenantPrivKey.PubKey(), + resp.UnbondingSig.Serialize(), + ) + + if err != nil { + return fmt.Errorf("failed to verify unbonding signature for unbonding tx: %w", err) + } + + return nil +} diff --git a/covenant-signer/signerapp/hardcoded_priv_key_retriever.go b/covenant-signer/signerapp/hardcodedprivkeyretriever.go similarity index 100% rename from covenant-signer/signerapp/hardcoded_priv_key_retriever.go rename to covenant-signer/signerapp/hardcodedprivkeyretriever.go diff --git a/covenant-signer/signerservice/handlers/sign_transactions.go b/covenant-signer/signerservice/handlers/signtransactions.go similarity index 100% rename from covenant-signer/signerservice/handlers/sign_transactions.go rename to covenant-signer/signerservice/handlers/signtransactions.go