From 751030a6586e17fc67305cd68121b285c39412b8 Mon Sep 17 00:00:00 2001 From: Tak Wai Wong <64229756+tak-hntlabs@users.noreply.github.com> Date: Wed, 28 Dec 2022 18:56:40 -0800 Subject: [PATCH] Add a config flag on dendrite to switch between zion contracts v1 / v2 (#1151) Temporary flag to implement v2 smart contract integration. Once v2 is done, will remove this flag. --- setup/config/config_publickey.go | 1 + setup/flags.go | 9 +- zion/contract_addresses.go | 15 ++ .../space-factory.json} | 0 zion/contracts/zion_localhost/spaces.json | 1 - zion/zion_authorization.go | 200 ++++++++++++------ 6 files changed, 160 insertions(+), 66 deletions(-) rename zion/contracts/{zion_localhost/spaceFactory.json => localhost_space_factory/space-factory.json} (100%) delete mode 100644 zion/contracts/zion_localhost/spaces.json diff --git a/setup/config/config_publickey.go b/setup/config/config_publickey.go index 909f538a0..42d3acb3b 100644 --- a/setup/config/config_publickey.go +++ b/setup/config/config_publickey.go @@ -26,6 +26,7 @@ type EthereumAuthConfig struct { NetworkUrl string `yaml:"network_url"` // Blockchain network provider URL ConfigChainID string `yaml:"chain_id"` // Blockchain chain ID. Env variable can replace this property. ConfigEnableAuthz string `yaml:"enable_authz"` // Enable / disable authorization during development. todo: remove this flag when feature is done. + ContractVersion string // todo: remove this setting when v2 migration is done. chainID int enableAuthz bool // todo: remove this flag when feature is done. } diff --git a/setup/flags.go b/setup/flags.go index 61c042dfc..fde7f2d4e 100644 --- a/setup/flags.go +++ b/setup/flags.go @@ -30,6 +30,7 @@ var ( version = flag.Bool("version", false, "Shows the current version and exits immediately.") enableRegistrationWithoutVerification = flag.Bool("really-enable-open-registration", false, "This allows open registration without secondary verification (reCAPTCHA). This is NOT RECOMMENDED and will SIGNIFICANTLY increase the risk that your server will be used to send spam or conduct attacks, which may result in your server being banned from rooms.") enableAuthorizationChecks = flag.Bool("enable-authz", false, "Enables authorization checks (aka space/channel gating).") + contractVersion = flag.String("contract-version", "v1", "Contract version to use. Valid values are v1 and v2. Default is v1. Remove this flag when v2 migration is done.") ) // ParseFlags parses the commandline flags and uses them to create a config. @@ -58,7 +59,13 @@ func ParseFlags(monolith bool) *config.Dendrite { // cmdline --enable-authz flag. env overrides it so that deployment scripts can set it. // todo: remove this flag when feature is done. cfg.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz = strconv.FormatBool(*enableAuthorizationChecks) - logrus.Info("enable-authz flag is set to ", *enableAuthorizationChecks) + logrus.Info("--enable-authz flag is set to ", *enableAuthorizationChecks) + + // cmdline --contract-version. Contract version to use. Valid values are v1 + // and v2. Default is v1. + // todo: Remove this flag when v2 migration is done. + cfg.ClientAPI.PublicKeyAuthentication.Ethereum.ContractVersion = *contractVersion + logrus.Info("--contract-version flag is set to ", *contractVersion) return cfg } diff --git a/zion/contract_addresses.go b/zion/contract_addresses.go index 4d50a0a2c..d21e7211c 100644 --- a/zion/contract_addresses.go +++ b/zion/contract_addresses.go @@ -10,6 +10,10 @@ type SpaceManagerContractAddresses struct { Tokengranted string `json:"tokengranted"` } +type SpaceFactoryContractAddress struct { + SpaceFactory string `json:"spaceFactory"` +} + func loadSpaceManagerAddresses(byteValue []byte) (*SpaceManagerContractAddresses, error) { var addresses SpaceManagerContractAddresses @@ -20,3 +24,14 @@ func loadSpaceManagerAddresses(byteValue []byte) (*SpaceManagerContractAddresses return &addresses, nil } + +func loadSpaceFactoryAddress(byteValue []byte) (*SpaceFactoryContractAddress, error) { + var address SpaceFactoryContractAddress + + err := json.Unmarshal(byteValue, &address) + if err != nil { + return nil, err + } + + return &address, nil +} diff --git a/zion/contracts/zion_localhost/spaceFactory.json b/zion/contracts/localhost_space_factory/space-factory.json similarity index 100% rename from zion/contracts/zion_localhost/spaceFactory.json rename to zion/contracts/localhost_space_factory/space-factory.json diff --git a/zion/contracts/zion_localhost/spaces.json b/zion/contracts/zion_localhost/spaces.json deleted file mode 100644 index 1a1660950..000000000 --- a/zion/contracts/zion_localhost/spaces.json +++ /dev/null @@ -1 +0,0 @@ -{"spaceFactory": "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707"} \ No newline at end of file diff --git a/zion/zion_authorization.go b/zion/zion_authorization.go index a88b350bd..169f15d73 100644 --- a/zion/zion_authorization.go +++ b/zion/zion_authorization.go @@ -3,30 +3,51 @@ package zion import ( _ "embed" "errors" + "fmt" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/matrix-org/dendrite/authorization" roomserver "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup/config" - zion_goerli "github.com/matrix-org/dendrite/zion/contracts/zion_goerli" - zion_localhost "github.com/matrix-org/dendrite/zion/contracts/zion_localhost" + zion_goerli "github.com/matrix-org/dendrite/zion/contracts/zion_goerli" // V1 smart contract + zion_localhost "github.com/matrix-org/dendrite/zion/contracts/zion_localhost" // v1 smart contract + + //goerli_space_factory "github.com/matrix-org/dendrite/zion/contracts/goerli_space_factory" // v2 smart contract + //goerli_space "github.com/matrix-org/dendrite/zion/contracts/goerli_space" // v2 smart contract + // v2 smart contract + localhost_space_factory "github.com/matrix-org/dendrite/zion/contracts/localhost_space_factory" // v2 smart contract log "github.com/sirupsen/logrus" ) +// V1 smart contract addresses +// //go:embed contracts/zion_localhost/space-manager.json -var localhostJson []byte +var localhostSpaceManagerJson []byte //go:embed contracts/zion_goerli/space-manager.json -var goerliJson []byte +var goerliSpaceManagerJson []byte + +// V2 smart contract addresses +// +//go:embed contracts/localhost_space_factory/space-factory.json +var localhostSpaceFactoryJson []byte + +// var goerliSpaceFactoryJson []byte var ErrSpaceDisabled = errors.New("space disabled") var ErrChannelDisabled = errors.New("channel disabled") type ZionAuthorization struct { chainId int - spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost - spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli - store Store + ethClient *ethclient.Client + spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost // v1 smart contract. Deprecating. + spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli // v1 smart contract. Deprecating. + localhostSpaceFactory *localhost_space_factory.LocalhostSpaceFactory // v2 localhost SpaceFactory smart contract + //localhostSpaces map[string]localhost_space.LocalhostSpace // v2 localhost map from networkId to a space contract + //goerliSpaceFactory *goerli_space_factory.LocalhostSpaceFactory // v2 goerli SpaceFactory smart contract + //goerliSpaces map[string]goerli_space.LocalhostSpace // v2 goerli map from networkId to a space contract + store Store } func NewZionAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEventsAPI) (authorization.Authorization, error) { @@ -35,30 +56,31 @@ func NewZionAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEv return nil, nil } + ethClient, err := GetEthClient(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl) + if err != nil { + log.Errorf("Cannot connect to eth client %v\n", cfg.PublicKeyAuthentication.Ethereum.NetworkUrl) + return nil, err + } + auth := ZionAuthorization{ - store: NewStore(roomQueryAPI), - chainId: cfg.PublicKeyAuthentication.Ethereum.GetChainID(), + store: NewStore(roomQueryAPI), + chainId: cfg.PublicKeyAuthentication.Ethereum.GetChainID(), + ethClient: ethClient, } - switch auth.chainId { - case 1337, 31337: - localhost, err := newZionSpaceManagerLocalhost(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl) + if cfg.PublicKeyAuthentication.Ethereum.ContractVersion == "v2" { + err := auth.initializeContractsV2() if err != nil { - log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) + return nil, err } - auth.spaceManagerLocalhost = localhost - - case 5: - goerli, err := newZionSpaceManagerGoerli(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl) + } else { + err := auth.initializeContractsV1() if err != nil { - log.Errorln("error instantiating ZionSpaceManagerGoerli", err) + return nil, err } - auth.spaceManagerGoerli = goerli - - default: - log.Errorf("Unsupported chain id: %d\n", auth.chainId) } + // no errors. return the auth object. return &auth, nil } @@ -100,6 +122,98 @@ func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bo return false, nil } +func newZionSpaceManagerLocalhost(ethClient *ethclient.Client) (*zion_localhost.ZionSpaceManagerLocalhost, error) { + jsonAddresses, err := loadSpaceManagerAddresses(localhostSpaceManagerJson) + if err != nil { + return nil, err + } + + address := common.HexToAddress(jsonAddresses.Spacemanager) + + spaceManager, err := zion_localhost.NewZionSpaceManagerLocalhost(address, ethClient) + if err != nil { + return nil, err + } + + return spaceManager, nil +} + +func newZionSpaceManagerGoerli(ethClient *ethclient.Client) (*zion_goerli.ZionSpaceManagerGoerli, error) { + addresses, err := loadSpaceManagerAddresses(goerliSpaceManagerJson) + if err != nil { + return nil, err + } + + address := common.HexToAddress(addresses.Spacemanager) + + spaceManager, err := zion_goerli.NewZionSpaceManagerGoerli(address, ethClient) + if err != nil { + return nil, err + } + + return spaceManager, nil +} + +func newSpaceFactoryLocalhost(ethClient *ethclient.Client) (*localhost_space_factory.LocalhostSpaceFactory, error) { + jsonAddress, err := loadSpaceFactoryAddress(localhostSpaceFactoryJson) + if err != nil { + return nil, err + } + + address := common.HexToAddress(jsonAddress.SpaceFactory) + + spaceFactory, err := localhost_space_factory.NewLocalhostSpaceFactory(address, ethClient) + if err != nil { + return nil, err + } + + return spaceFactory, nil +} + +func (za *ZionAuthorization) initializeContractsV1() error { + switch za.chainId { + case 1337, 31337: + localhost, err := newZionSpaceManagerLocalhost(za.ethClient) + if err != nil { + log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) + return err + } + za.spaceManagerLocalhost = localhost + + case 5: + goerli, err := newZionSpaceManagerGoerli(za.ethClient) + if err != nil { + log.Errorln("error instantiating ZionSpaceManagerGoerli", err) + return err + } + za.spaceManagerGoerli = goerli + default: + errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) + log.Error(errMsg) + return errors.New(errMsg) + } + // no errors. + return nil +} + +func (za *ZionAuthorization) initializeContractsV2() error { + switch za.chainId { + case 1337, 31337: + localhost, err := newSpaceFactoryLocalhost(za.ethClient) + if err != nil { + log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) + return err + } + za.localhostSpaceFactory = localhost + default: + errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) + log.Error(errMsg) + return errors.New(errMsg) + } + // no errors. + return nil +} + func (za *ZionAuthorization) isSpaceChannelDisabledLocalhost(roomInfo RoomInfo) (bool, error) { if za.spaceManagerLocalhost == nil { return false, errors.New("error fetching space manager contract") @@ -185,45 +299,3 @@ func (za *ZionAuthorization) isAllowedGoerli( return false, nil } - -func newZionSpaceManagerLocalhost(endpointUrl string) (*zion_localhost.ZionSpaceManagerLocalhost, error) { - addresses, err := loadSpaceManagerAddresses(localhostJson) - if err != nil { - return nil, err - } - - address := common.HexToAddress(addresses.Spacemanager) - - client, err := GetEthClient(endpointUrl) - if err != nil { - return nil, err - } - - spaceManager, err := zion_localhost.NewZionSpaceManagerLocalhost(address, client) - if err != nil { - return nil, err - } - - return spaceManager, nil -} - -func newZionSpaceManagerGoerli(endpointUrl string) (*zion_goerli.ZionSpaceManagerGoerli, error) { - addresses, err := loadSpaceManagerAddresses(goerliJson) - if err != nil { - return nil, err - } - - address := common.HexToAddress((addresses.Spacemanager)) - - client, err := GetEthClient(endpointUrl) - if err != nil { - return nil, err - } - - spaceManager, err := zion_goerli.NewZionSpaceManagerGoerli(address, client) - if err != nil { - return nil, err - } - - return spaceManager, nil -}