diff --git a/README.md b/README.md index 915e57dc..673c1780 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # OPinit CosmosSDK Modules + The OPinit Stack is a versatile framework designed for CosmosSDK, facilitating the development of vm-agnostic Optimistic Rollups. This framework aligns closely with the interface of Optimism's Bedrock, promoting a straightforward user experience. Leveraging the Initia L1 Governance model, it addresses fraud-proof disputes efficiently. ## Optimistic Rollup Architecture ![image](https://github.com/initia-labs/OPinit/assets/160459432/77103140-73ef-41f2-95ba-682bee616f4e) - ### L1 Components #### [Bridge Module](./specs/l1_bridge.md) diff --git a/contrib/launchtools/README.md b/contrib/launchtools/README.md index 8d3ee01f..2aed6ba8 100644 --- a/contrib/launchtools/README.md +++ b/contrib/launchtools/README.md @@ -28,8 +28,8 @@ minitiad launch $TARGET_NETWORK --with-config [path-to-config] ```json { "l1_config": { - "chain_id": "initiation-1", - "rpc_url": "https://rpc.initiation-1.initia.xyz:443", + "chain_id": "initiation-2", + "rpc_url": "https://rpc.initiation-2.initia.xyz:443", "gas_prices": "0.015uinit" }, "l2_config": { @@ -38,28 +38,31 @@ minitiad launch $TARGET_NETWORK --with-config [path-to-config] "moniker": "operator" }, "op_bridge": { - "output_submission_start_height": "1", - "output_submission_interval": 3600000000000, - "output_finalization_period": 3600000000000, - "batch_submission_target": "INITIA" + "output_submission_start_height": 1, + "output_submission_interval": "1h0m0s", + "output_finalization_period": "168h0m0s", + "batch_submission_target": "INITIA", + "enable_oracle": true }, "system_keys": { "validator": { - "address": "init12z54lfqgp7zapzuuk2m4h6mjz84qzca8j0wm4x", + "l2_address": "init12z54lfqgp7zapzuuk2m4h6mjz84qzca8j0wm4x", "mnemonic": "digital kingdom slim fall cereal aspect expose trade once antique treat spatial unfair trip silver diesel other friend invest valve human blouse decrease salt" }, "bridge_executor": { - "address": "init13skjgs2x96c4sk9mfkfdzjywm75l6wy63j5gyn", + "l1_address": "init13skjgs2x96c4sk9mfkfdzjywm75l6wy63j5gyn", + "l2_address": "init13skjgs2x96c4sk9mfkfdzjywm75l6wy63j5gyn", "mnemonic": "junk aunt group member rebel dinosaur will trial jacket core club obscure morning unit fame round render napkin boy chest same patrol twelve medal" }, "output_submitter": { - "address": "init1f4lu0ze9c7zegrrjfpymjvztucqz48z3cy8p5f" + "l1_address": "init1f4lu0ze9c7zegrrjfpymjvztucqz48z3cy8p5f" }, "batch_submitter": { - "address": "init1hqv5xqt7lckdj9p5kfp2q5auc5z37p2vyt4d72" + "da_address": "init1hqv5xqt7lckdj9p5kfp2q5auc5z37p2vyt4d72" }, "challenger": { - "address": "init1gn0yjtcma92y27c0z84ratxf6juy69lpln6u88" + "l1_address": "init1gn0yjtcma92y27c0z84ratxf6juy69lpln6u88", + "l2_address": "init1gn0yjtcma92y27c0z84ratxf6juy69lpln6u88" } }, "genesis_accounts": [ @@ -70,12 +73,6 @@ minitiad launch $TARGET_NETWORK --with-config [path-to-config] { "address": "init13skjgs2x96c4sk9mfkfdzjywm75l6wy63j5gyn" }, - { - "address": "init1f4lu0ze9c7zegrrjfpymjvztucqz48z3cy8p5f" - }, - { - "address": "init1hqv5xqt7lckdj9p5kfp2q5auc5z37p2vyt4d72" - }, { "address": "init1gn0yjtcma92y27c0z84ratxf6juy69lpln6u88" } diff --git a/contrib/launchtools/cmd.go b/contrib/launchtools/cmd.go index 3205a588..f01c0219 100644 --- a/contrib/launchtools/cmd.go +++ b/contrib/launchtools/cmd.go @@ -96,7 +96,7 @@ Artifact written to `, path.Join(clientCtx.HomeDir, artifactsDir, "config.json"), - path.Join(clientCtx.HomeDir, artifactsDir, "artifact.json"), + path.Join(clientCtx.HomeDir, artifactsDir, "artifacts.json"), ); err != nil { return errors.Wrap(err, "failed to write artifacts to stdout") } diff --git a/contrib/launchtools/config.go b/contrib/launchtools/config.go index 4721dfab..e9d699be 100644 --- a/contrib/launchtools/config.go +++ b/contrib/launchtools/config.go @@ -12,8 +12,6 @@ import ( "github.com/pkg/errors" "github.com/cosmos/cosmos-sdk/client/input" - "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/go-bip39" @@ -74,7 +72,7 @@ func (i *Config) Finalize(buf *bufio.Reader) error { if err := i.OpBridge.Finalize(buf); err != nil { return err } - if err := i.SystemKeys.Finalize(buf); err != nil { + if err := i.SystemKeys.Finalize(buf, i.OpBridge.BatchSubmissionTarget); err != nil { return err } if err := i.GenesisAccounts.Finalize(*i.SystemKeys); err != nil { @@ -286,6 +284,7 @@ func (l1config *L1Config) Finalize(buf *bufio.Reader) error { type SystemAccount struct { L1Address string `json:"l1_address,omitempty"` L2Address string `json:"l2_address,omitempty"` + DAAddress string `json:"da_address,omitempty"` Mnemonic string `json:"mnemonic,omitempty"` } @@ -304,6 +303,10 @@ func (gas *GenesisAccounts) Finalize(systemKeys SystemKeys) error { return errors.New("systemKeys must be of type launcher.Account") } + if k.L2Address == "" { + continue + } + found := false for _, ga := range *gas { if ga.Address == k.L2Address { @@ -360,31 +363,7 @@ func generateMnemonic() (string, error) { return mnemonic, nil } -func deriveAddress(mnemonic string) (string, string, error) { - algo := hd.Secp256k1 - derivedPriv, err := algo.Derive()( - mnemonic, - keyring.DefaultBIP39Passphrase, - sdk.GetConfig().GetFullBIP44Path(), - ) - if err != nil { - return "", "", errors.Wrap(err, "failed to derive private key") - } - - privKey := algo.Generate()(derivedPriv) - addrBz := privKey.PubKey().Address() - - // use init Bech32 prefix for l1 address - l1Addr, err := utils.L1AddressCodec().BytesToString(addrBz) - if err != nil { - return "", "", errors.Wrap(err, "failed to convert address to bech32") - } - - l2Addr, err := utils.L2AddressCodec().BytesToString(addrBz) - return l1Addr, l2Addr, err -} - -func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader) error { +func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader, batchSubmissionTarget ophosttypes.BatchInfo_ChainType) error { if systemKeys.Validator == nil { mnemonic, err := generateMnemonic() if err != nil { @@ -392,13 +371,12 @@ func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader) error { } // derive address - l1Addr, l2Addr, err := deriveAddress(mnemonic) + l2Addr, err := utils.DeriveL2Address(mnemonic) if err != nil { return errors.Wrap(err, "failed to derive address") } systemKeys.Validator = &SystemAccount{ - L1Address: l1Addr, L2Address: l2Addr, Mnemonic: mnemonic, } @@ -410,14 +388,13 @@ func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader) error { } // derive address - l1Addr, l2Addr, err := deriveAddress(mnemonic) + daAddr, err := utils.DeriveDAAddress(mnemonic, batchSubmissionTarget) if err != nil { return errors.Wrap(err, "failed to derive address") } systemKeys.BatchSubmitter = &SystemAccount{ - L1Address: l1Addr, - L2Address: l2Addr, + DAAddress: daAddr, Mnemonic: mnemonic, } } @@ -432,7 +409,11 @@ func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader) error { } // derive address - l1Addr, l2Addr, err := deriveAddress(mnemonic) + l1Addr, err := utils.DeriveL1Address(mnemonic) + if err != nil { + return errors.Wrap(err, "failed to derive address") + } + l2Addr, err := utils.DeriveL2Address(mnemonic) if err != nil { return errors.Wrap(err, "failed to derive address") } @@ -450,7 +431,11 @@ func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader) error { } // derive address - l1Addr, l2Addr, err := deriveAddress(mnemonic) + l1Addr, err := utils.DeriveL1Address(mnemonic) + if err != nil { + return errors.Wrap(err, "failed to derive address") + } + l2Addr, err := utils.DeriveL2Address(mnemonic) if err != nil { return errors.Wrap(err, "failed to derive address") } @@ -468,14 +453,13 @@ func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader) error { } // derive address - l1Addr, l2Addr, err := deriveAddress(mnemonic) + l1Addr, err := utils.DeriveL1Address(mnemonic) if err != nil { return errors.Wrap(err, "failed to derive address") } systemKeys.OutputSubmitter = &SystemAccount{ L1Address: l1Addr, - L2Address: l2Addr, Mnemonic: mnemonic, } } @@ -487,13 +471,13 @@ func (systemKeys *SystemKeys) Finalize(buf *bufio.Reader) error { if systemKeys.BridgeExecutor.L1Address == "" || systemKeys.BridgeExecutor.L2Address == "" || systemKeys.BridgeExecutor.Mnemonic == "" { return errors.New("bridge_executor account not initialized") } - if systemKeys.BatchSubmitter.L1Address == "" { + if systemKeys.BatchSubmitter.DAAddress == "" { return errors.New("batch_submitter account not initialized") } if systemKeys.OutputSubmitter.L1Address == "" { return errors.New("output_submitter account not initialized") } - if systemKeys.Challenger.L1Address == "" { + if systemKeys.Challenger.L1Address == "" || systemKeys.Challenger.L2Address == "" { return errors.New("challenger account not initialized") } diff --git a/contrib/launchtools/steps/genesis.go b/contrib/launchtools/steps/genesis.go index a7d1f4b7..d849c993 100644 --- a/contrib/launchtools/steps/genesis.go +++ b/contrib/launchtools/steps/genesis.go @@ -322,7 +322,6 @@ func addFeeWhitelists(cdc codec.Codec, genesisAppState map[string]json.RawMessag ) { opchildState := opchildtypes.GetGenesisStateFromAppState(cdc, genesisAppState) opchildState.Params.FeeWhitelist = append(opchildState.Params.FeeWhitelist, whitelistAddrs...) - return opchildState, nil } diff --git a/contrib/launchtools/steps/opbridge.go b/contrib/launchtools/steps/opbridge.go index 99dd0c94..63a63d35 100644 --- a/contrib/launchtools/steps/opbridge.go +++ b/contrib/launchtools/steps/opbridge.go @@ -44,7 +44,7 @@ func InitializeOpBridge( config.SystemKeys.BridgeExecutor.L1Address, config.SystemKeys.Challenger.L1Address, config.SystemKeys.OutputSubmitter.L1Address, - config.SystemKeys.BatchSubmitter.L1Address, + config.SystemKeys.BatchSubmitter.DAAddress, config.OpBridge.BatchSubmissionTarget, *config.OpBridge.OutputSubmissionInterval, *config.OpBridge.OutputFinalizationPeriod, diff --git a/contrib/launchtools/utils/address.go b/contrib/launchtools/utils/address.go index 9ced3f40..b4b56291 100644 --- a/contrib/launchtools/utils/address.go +++ b/contrib/launchtools/utils/address.go @@ -1,9 +1,17 @@ package utils import ( + "github.com/pkg/errors" + + cmtcrypto "github.com/cometbft/cometbft/crypto" + "cosmossdk.io/core/address" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" + + ophosttypes "github.com/initia-labs/OPinit/x/ophost/types" ) func L1AddressCodec() address.Codec { @@ -14,6 +22,10 @@ func L2AddressCodec() address.Codec { return authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) } +func CelestiaAddressCodec() address.Codec { + return authcodec.NewBech32Codec("celestia") +} + func HackBech32Prefix(prefix string) func() { originPrefix := sdk.GetConfig().GetBech32AccountAddrPrefix() originPubPrefix := sdk.GetConfig().GetBech32AccountPubPrefix() @@ -23,3 +35,47 @@ func HackBech32Prefix(prefix string) func() { sdk.GetConfig().SetBech32PrefixForAccount(originPrefix, originPubPrefix) } } + +func DeriveL1Address(mnemonic string) (string, error) { + return deriveAddress(mnemonic, L1AddressCodec()) +} + +func DeriveL2Address(mnemonic string) (string, error) { + return deriveAddress(mnemonic, L2AddressCodec()) +} + +func DeriveDAAddress(mnemonic string, chainType ophosttypes.BatchInfo_ChainType) (string, error) { + var codec address.Codec + switch chainType { + case ophosttypes.BatchInfo_CHAIN_TYPE_INITIA: + codec = L1AddressCodec() + case ophosttypes.BatchInfo_CHAIN_TYPE_CELESTIA: + codec = CelestiaAddressCodec() + default: + return "", errors.New("unsupported chain type") + } + return deriveAddress(mnemonic, codec) +} + +func deriveAddress(mnemonic string, codec address.Codec) (string, error) { + addrBz, err := deriveAddressBz(mnemonic) + if err != nil { + return "", errors.Wrap(err, "failed to convert address to bech32") + } + return codec.BytesToString(addrBz) +} + +func deriveAddressBz(mnemonic string) (cmtcrypto.Address, error) { + algo := hd.Secp256k1 + derivedPriv, err := algo.Derive()( + mnemonic, + keyring.DefaultBIP39Passphrase, + sdk.GetConfig().GetFullBIP44Path(), + ) + if err != nil { + return nil, errors.Wrap(err, "failed to derive private key") + } + + privKey := algo.Generate()(derivedPriv) + return privKey.PubKey().Address(), nil +} diff --git a/x/ophost/keeper/msg_server.go b/x/ophost/keeper/msg_server.go index 34dc2cde..9af1bf82 100644 --- a/x/ophost/keeper/msg_server.go +++ b/x/ophost/keeper/msg_server.go @@ -347,6 +347,7 @@ func (ms MsgServer) FinalizeTokenWithdrawal(ctx context.Context, req *types.MsgF return &types.MsgFinalizeTokenWithdrawalResponse{}, nil } +//nolint:dupl func (ms MsgServer) UpdateProposer(ctx context.Context, req *types.MsgUpdateProposer) (*types.MsgUpdateProposerResponse, error) { if err := req.Validate(ms.authKeeper.AddressCodec()); err != nil { return nil, err @@ -391,6 +392,7 @@ func (ms MsgServer) UpdateProposer(ctx context.Context, req *types.MsgUpdateProp }, nil } +//nolint:dupl func (ms MsgServer) UpdateChallenger(ctx context.Context, req *types.MsgUpdateChallenger) (*types.MsgUpdateChallengerResponse, error) { if err := req.Validate(ms.authKeeper.AddressCodec()); err != nil { return nil, err