Skip to content

Commit

Permalink
test: start FP in op e2e (ethereum-optimism#418)
Browse files Browse the repository at this point in the history
  • Loading branch information
bap2pecs authored Jun 23, 2024
1 parent c675382 commit 9e411e4
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 13 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ build_tags := $(BUILD_TAGS)
build_args := $(BUILD_ARGS)

PACKAGES_E2E=$(shell go list ./... | grep '/itest')
PACKAGES_E2E_OP=$(shell go list -tags=e2e_op ./... | grep '/itest')

ifeq ($(LINK_STATICALLY),true)
ldflags += -linkmode=external -extldflags "-Wl,-z,muldefs -static" -v
Expand Down Expand Up @@ -83,11 +84,11 @@ clean-e2e:
test-e2e: install-babylond install-wasmd
make clean-e2e
go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e
go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e_op
go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E_OP) -count=1 --tags=e2e_op

test-e2e-op: install-babylond
make clean-e2e
go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e_op
go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E_OP) -count=1 --tags=e2e_op

###############################################################################
### Protobuf ###
Expand Down
Binary file removed itest/bytecode/op_finality_gadget.wasm
Binary file not shown.
Binary file added itest/bytecode/op_finality_gadget_f149c8b.wasm
Binary file not shown.
3 changes: 3 additions & 0 deletions itest/opstackl2/op_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ func TestOpSubmitFinalitySignature(t *testing.T) {
// mocked address which is diff than the deployed one on the fly
ctm.OpL2ConsumerCtrl.Cfg.OPFinalityGadgetAddress = resp.Contracts[0]
t.Logf("Deployed op finality contract address: %s", resp.Contracts[0])

// register FP in Babylon Chain
_ = ctm.StartFinalityProvider(t, 1)
}
160 changes: 149 additions & 11 deletions itest/opstackl2/op_test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,46 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"time"

sdkmath "cosmossdk.io/math"
wasmdtypes "github.com/CosmWasm/wasmd/x/wasm/types"
bbnclient "github.com/babylonchain/babylon/client/client"
bbncfg "github.com/babylonchain/babylon/client/config"
bbntypes "github.com/babylonchain/babylon/types"
bsctypes "github.com/babylonchain/babylon/x/btcstkconsumer/types"
bbncc "github.com/babylonchain/finality-provider/clientcontroller/babylon"
"github.com/babylonchain/finality-provider/clientcontroller/opstackl2"
"github.com/babylonchain/finality-provider/eotsmanager/client"
eotsconfig "github.com/babylonchain/finality-provider/eotsmanager/config"
fpcfg "github.com/babylonchain/finality-provider/finality-provider/config"
"github.com/babylonchain/finality-provider/finality-provider/service"
e2etest "github.com/babylonchain/finality-provider/itest"
"github.com/babylonchain/finality-provider/types"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdkquery "github.com/cosmos/cosmos-sdk/types/query"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)

const (
opFinalityGadgetContractPath = "../bytecode/op_finality_gadget.wasm"
opFinalityGadgetContractPath = "../bytecode/op_finality_gadget_f149c8b.wasm"
opConsumerId = "op-stack-l2-12345"
)

type OpL2ConsumerTestManager struct {
BabylonHandler *e2etest.BabylonNodeHandler
FpConfig *fpcfg.Config
BBNClient *bbncc.BabylonController
OpL2ConsumerCtrl *opstackl2.OPStackL2ConsumerController
BabylonHandler *e2etest.BabylonNodeHandler
BBNClient *bbncc.BabylonController
EOTSClient *client.EOTSManagerGRpcClient
EOTSConfig *eotsconfig.Config
EOTSServerHandler *e2etest.EOTSServerHandler
FpApp *service.FinalityProviderApp
FpConfig *fpcfg.Config
OpL2ConsumerCtrl *opstackl2.OPStackL2ConsumerController
// TODO: not sure if needed, if not can remove
StakingParams *types.StakingParams
CovenantPrivKeys []*btcec.PrivateKey
Expand Down Expand Up @@ -63,15 +76,40 @@ func StartOpL2ConsumerManager(t *testing.T) *OpL2ConsumerTestManager {
bc, err := bbncc.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger)
require.NoError(t, err)

// 3. new op consumer controller
// 3. register consumer to Babylon
txRes, err := bc.RegisterConsumerChain(opConsumerId, opConsumerId, opConsumerId)
require.NoError(t, err)
t.Logf("Register consumer %s to Babylon %s", opConsumerId, txRes.TxHash)

// 4. new op consumer controller
opcc, err := opstackl2.NewOPStackL2ConsumerController(mockOpL2ConsumerCtrlConfig(bh.GetNodeDataDir()), logger)
require.NoError(t, err)

// 5. prepare EOTS manager
eotsHomeDir := filepath.Join(testDir, "eots-home")
eotsCfg := eotsconfig.DefaultConfigWithHomePath(eotsHomeDir)
eh := e2etest.NewEOTSServerHandler(t, eotsCfg, eotsHomeDir)
eh.Start()
eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress)
require.NoError(t, err)

// 6. prepare finality-provider
fpdb, err := cfg.DatabaseConfig.GetDbBackend()
require.NoError(t, err)
fpApp, err := service.NewFinalityProviderApp(cfg, bc, opcc, eotsCli, fpdb, logger)
require.NoError(t, err)
err = fpApp.Start()
require.NoError(t, err)

ctm := &OpL2ConsumerTestManager{
BabylonHandler: bh,
FpConfig: cfg,
BabylonHandler: bh,
BBNClient: bc,
EOTSClient: eotsCli,
EOTSConfig: eotsCfg,
EOTSServerHandler: eh,
FpApp: fpApp,
FpConfig: cfg,
// TODO: might not need this bc field
BBNClient: bc,
OpL2ConsumerCtrl: opcc,
CovenantPrivKeys: covenantPrivKeys,
baseDir: testDir,
Expand Down Expand Up @@ -118,7 +156,101 @@ func (ctm *OpL2ConsumerTestManager) WaitForServicesStart(t *testing.T) {
ctm.StakingParams = params
return true
}, e2etest.EventuallyWaitTimeOut, e2etest.EventuallyPollTime)
t.Logf("Babylon node is started")
t.Logf("Babylon node has started")
}

func (ctm *OpL2ConsumerTestManager) StartFinalityProvider(t *testing.T, n int) []*service.FinalityProviderInstance {
app := ctm.FpApp

for i := 0; i < n; i++ {
fpName := e2etest.FpNamePrefix + strconv.Itoa(i)
moniker := e2etest.MonikerPrefix + strconv.Itoa(i)
commission := sdkmath.LegacyZeroDec()
desc := e2etest.NewDescription(moniker)
cfg := app.GetConfig()
_, err := service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, fpName, keyring.BackendTest, e2etest.Passphrase, e2etest.HdPath, "")
require.NoError(t, err)
res, err := app.CreateFinalityProvider(fpName, opConsumerId, e2etest.Passphrase, e2etest.HdPath, desc, &commission)
require.NoError(t, err)
fpPk, err := bbntypes.NewBIP340PubKeyFromHex(res.FpInfo.BtcPkHex)
require.NoError(t, err)
regRes, err := app.RegisterFinalityProvider(fpPk.MarshalHex())
t.Logf("Registered Finality Provider %s", regRes.TxHash)
require.NoError(t, err)
err = app.StartHandlingFinalityProvider(fpPk, e2etest.Passphrase)
require.NoError(t, err)
fpIns, err := app.GetFinalityProviderInstance(fpPk)
require.NoError(t, err)
require.True(t, fpIns.IsRunning())
require.NoError(t, err)

// check finality providers on Babylon side
require.Eventually(t, func() bool {
fps, err := ctm.QueryFinalityProviders(opConsumerId)
if err != nil {
t.Logf("failed to query finality providers from Babylon %s", err.Error())
return false
}

if len(fps) != i+1 {
return false
}

for _, fp := range fps {
if !strings.Contains(fp.Description.Moniker, e2etest.MonikerPrefix) {
return false
}
if !fp.Commission.Equal(sdkmath.LegacyZeroDec()) {
return false
}
}

return true
}, e2etest.EventuallyWaitTimeOut, e2etest.EventuallyPollTime)
}

fpInsList := app.ListFinalityProviderInstances()
require.Equal(t, n, len(fpInsList))

t.Logf("The test manager is running with %v finality-provider(s)", len(fpInsList))

for i, fp := range fpInsList {
t.Logf("The num %d finality-provider pubkeyhex %s", i, fp.GetBtcPkHex())
}

return fpInsList
}

func (ctm *OpL2ConsumerTestManager) QueryFinalityProviders(consumerId string) ([]*bsctypes.FinalityProviderResponse, error) {
var fps []*bsctypes.FinalityProviderResponse
pagination := &sdkquery.PageRequest{
Limit: 100,
}

bbnConfig := fpcfg.BBNConfigToBabylonConfig(ctm.FpConfig.BabylonConfig)
logger := zap.NewNop()
bc, err := bbnclient.New(
&bbnConfig,
logger,
)
if err != nil {
return nil, fmt.Errorf("failed to create Babylon client: %w", err)
}

for {
res, err := bc.QueryConsumerFinalityProviders(consumerId, pagination)
if err != nil {
return nil, fmt.Errorf("failed to query finality providers: %v", err)
}
fps = append(fps, res.FinalityProviders...)
if res.Pagination == nil || res.Pagination.NextKey == nil {
break
}

pagination.Key = res.Pagination.NextKey
}

return fps, nil
}

func (ctm *OpL2ConsumerTestManager) StoreWasmCode(wasmFile string) error {
Expand Down Expand Up @@ -189,8 +321,14 @@ func (ctm *OpL2ConsumerTestManager) GetLatestCodeId() (uint64, error) {
}

func (ctm *OpL2ConsumerTestManager) Stop(t *testing.T) {
err := ctm.BabylonHandler.Stop()
var err error
// FpApp has to stop first or you will get "rpc error: desc = account xxx not found: key not found" error
// b/c when Babylon daemon is stopped, FP won't be able to find the keyring backend
err = ctm.FpApp.Stop()
require.NoError(t, err)
err = ctm.BabylonHandler.Stop()
require.NoError(t, err)
ctm.EOTSServerHandler.Stop()
err = os.RemoveAll(ctm.baseDir)
require.NoError(t, err)
}

0 comments on commit 9e411e4

Please sign in to comment.