Add goerli types to client lib and dendrite (#1247)

This commit is contained in:
Tak Wai Wong 2023-01-19 09:42:09 -08:00 committed by GitHub
parent 2020161369
commit 425b28f2cc
6 changed files with 325 additions and 139 deletions

View file

@ -14,7 +14,7 @@ func NewRoomserverAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.Q
auth, err := zion.NewZionAuthorization(cfg, roomQueryAPI)
if err != nil {
log.Errorln("Failed to initialise Zion authorization manager. Using default.", err)
log.Errorf("failed to initialise Zion authorization manager, using default. Error: %v", err)
} else {
return auth
}

View file

@ -16,22 +16,18 @@ type SpaceFactoryContractAddress struct {
func loadSpaceManagerAddresses(byteValue []byte) (*SpaceManagerContractAddresses, error) {
var addresses SpaceManagerContractAddresses
err := json.Unmarshal(byteValue, &addresses)
if err != nil {
return nil, err
}
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
}

25
zion/space_contract.go Normal file
View file

@ -0,0 +1,25 @@
package zion
import (
"github.com/ethereum/go-ethereum/common"
"github.com/matrix-org/dendrite/authorization"
)
type SpaceContract interface {
IsSpaceDisabled(spaceNetworkId string) (bool, error)
IsChannelDisabled(
spaceNetworkId string,
channelNetworkId string,
) (bool, error)
IsEntitledToSpace(
spaceNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error)
IsEntitledToChannel(
spaceNetworkId string,
channelNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error)
}

View file

@ -0,0 +1,125 @@
package zion
import (
_ "embed"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/gologme/log"
"github.com/matrix-org/dendrite/authorization"
"github.com/matrix-org/dendrite/zion/contracts/goerli_space"
"github.com/matrix-org/dendrite/zion/contracts/goerli_space_factory"
)
//go:embed contracts/goerli_space_factory/space-factory.json
var goerliSpaceFactoryJson []byte
type SpaceContractGoerli struct {
ethClient *ethclient.Client
spaceFactory *goerli_space_factory.GoerliSpaceFactory
spaces map[string]*goerli_space.GoerliSpace
}
func NewSpaceContractGoerli(ethClient *ethclient.Client) (*SpaceContractGoerli, error) {
jsonAddress, err := loadSpaceFactoryAddress(goerliSpaceFactoryJson)
if err != nil {
log.Errorf("error parsing goerli space factory contract address %v. Error: %v", jsonAddress, err)
return nil, err
}
address := common.HexToAddress(jsonAddress.SpaceFactory)
spaceFactory, err := goerli_space_factory.NewGoerliSpaceFactory(address, ethClient)
if err != nil {
log.Errorf("error fetching goerli space factory contract with address %v. Error: %v", jsonAddress, err)
return nil, err
}
// no errors.
var spaceContract = &SpaceContractGoerli{
ethClient: ethClient,
spaceFactory: spaceFactory,
spaces: make(map[string]*goerli_space.GoerliSpace),
}
return spaceContract, nil
}
func (za *SpaceContractGoerli) IsEntitledToSpace(
spaceNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isEntitled, err := space.IsEntitledToSpace(
nil,
user,
permission.String(),
)
if err != nil {
return false, err
}
return isEntitled, nil
}
func (za *SpaceContractGoerli) IsEntitledToChannel(
spaceNetworkId string,
channelNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
// channel entitlement check
isEntitled, err := space.IsEntitledToChannel(
nil,
channelNetworkId,
user,
permission.String(),
)
return isEntitled, err
}
func (za *SpaceContractGoerli) IsSpaceDisabled(spaceNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isDisabled, err := space.Disabled(nil)
return isDisabled, err
}
func (za *SpaceContractGoerli) IsChannelDisabled(spaceNetworkId string, channelNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
channelIdHash := NetworkIdToHash(channelNetworkId)
channel, err := space.GetChannelByHash(nil, channelIdHash)
if err != nil {
return false, err
}
return channel.Disabled, err
}
func (za *SpaceContractGoerli) getSpace(networkId string) (*goerli_space.GoerliSpace, error) {
if za.spaces[networkId] == nil {
// convert the networkId to keccak256 spaceIdHash
spaceIdHash := NetworkIdToHash(networkId)
// then use the spaceFactory to fetch the space address
spaceAddress, err := za.spaceFactory.SpaceByHash(nil, spaceIdHash)
if err != nil {
return nil, err
}
// cache the space for future use
space, err := goerli_space.NewGoerliSpace(spaceAddress, za.ethClient)
if err != nil {
return nil, err
}
za.spaces[networkId] = space
}
return za.spaces[networkId], nil
}

View file

@ -0,0 +1,120 @@
package zion
import (
_ "embed"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/matrix-org/dendrite/authorization"
"github.com/matrix-org/dendrite/zion/contracts/localhost_space"
"github.com/matrix-org/dendrite/zion/contracts/localhost_space_factory"
log "github.com/sirupsen/logrus"
)
//go:embed contracts/localhost_space_factory/space-factory.json
var localhostSpaceFactoryJson []byte
type SpaceContractLocalhost struct {
ethClient *ethclient.Client
spaceFactory *localhost_space_factory.LocalhostSpaceFactory
spaces map[string]*localhost_space.LocalhostSpace
}
func NewSpaceContractLocalhost(ethClient *ethclient.Client) (*SpaceContractLocalhost, error) {
jsonAddress, err := loadSpaceFactoryAddress(localhostSpaceFactoryJson)
if err != nil {
log.Errorf("error parsing localhost space factory contract address %v. Error: %v", jsonAddress, err)
return nil, err
}
address := common.HexToAddress(jsonAddress.SpaceFactory)
spaceFactory, err := localhost_space_factory.NewLocalhostSpaceFactory(address, ethClient)
if err != nil {
log.Errorf("error fetching localhost space factory contract with address %v. Error: %v", jsonAddress, err)
return nil, err
}
// no errors.
var spaceContract = &SpaceContractLocalhost{
ethClient: ethClient,
spaceFactory: spaceFactory,
spaces: make(map[string]*localhost_space.LocalhostSpace),
}
return spaceContract, nil
}
func (za *SpaceContractLocalhost) IsEntitledToSpace(
spaceNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isEntitled, err := space.IsEntitledToSpace(
nil,
user,
permission.String(),
)
return isEntitled, err
}
func (za *SpaceContractLocalhost) IsEntitledToChannel(
spaceNetworkId string,
channelNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
// channel entitlement check
isEntitled, err := space.IsEntitledToChannel(
nil,
channelNetworkId,
user,
permission.String(),
)
return isEntitled, err
}
func (za *SpaceContractLocalhost) IsSpaceDisabled(spaceNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isDisabled, err := space.Disabled(nil)
return isDisabled, err
}
func (za *SpaceContractLocalhost) IsChannelDisabled(spaceNetworkId string, channelNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
channelIdHash := NetworkIdToHash(channelNetworkId)
channel, err := space.GetChannelByHash(nil, channelIdHash)
return channel.Disabled, err
}
func (za *SpaceContractLocalhost) getSpace(networkId string) (*localhost_space.LocalhostSpace, error) {
if za.spaces[networkId] == nil {
// convert the networkId to keccak256 spaceIdHash
spaceIdHash := NetworkIdToHash(networkId)
// then use the spaceFactory to fetch the space address
spaceAddress, err := za.spaceFactory.SpaceByHash(nil, spaceIdHash)
if err != nil {
return nil, err
}
// cache the space for future use
space, err := localhost_space.NewLocalhostSpace(spaceAddress, za.ethClient)
if err != nil {
return nil, err
}
za.spaces[networkId] = space
}
return za.spaces[networkId], nil
}

View file

@ -9,51 +9,40 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/matrix-org/dendrite/authorization"
"github.com/matrix-org/dendrite/zion/contracts/localhost_space"
"github.com/matrix-org/dendrite/zion/contracts/localhost_space_factory"
//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
log "github.com/sirupsen/logrus"
)
// v2 smart contract addresses
//
//go:embed contracts/localhost_space_factory/space-factory.json
var localhostSpaceFactoryJson []byte
// var goerliSpaceFactoryJson []byte
// v2 smart contracts
type ZionAuthorizationV2 struct {
chainId int
ethClient *ethclient.Client
store Store
localhostSpaceFactory *localhost_space_factory.LocalhostSpaceFactory
localhostSpaces map[string]*localhost_space.LocalhostSpace
//goerliSpaceFactory *goerli_space_factory.GoerliSpaceFactory
//goerliSpaces map[string]*goerli_space.GoerliSpace
chainId int
ethClient *ethclient.Client
store Store
spaceContract SpaceContract
}
func NewZionAuthorizationV2(chainId int, ethClient *ethclient.Client, store Store) (authorization.Authorization, error) {
za := &ZionAuthorizationV2{
chainId: chainId,
ethClient: ethClient,
store: store,
localhostSpaces: make(map[string]*localhost_space.LocalhostSpace),
//goerliSpaces: make(map[string]*goerli_space.GoerliSpace),
chainId: chainId,
ethClient: ethClient,
store: store,
}
switch za.chainId {
case 1337, 31337:
localhost, err := newSpaceFactoryLocalhost(za.ethClient)
localhost, err := NewSpaceContractLocalhost(za.ethClient)
if err != nil {
log.Errorln("error instantiating ZionSpaceManagerLocalhost", err)
log.Errorf("error instantiating SpaceContractLocalhost. Error: %v", err)
return nil, err
}
za.localhostSpaceFactory = localhost
za.spaceContract = localhost
case 5:
goerli, err := NewSpaceContractGoerli(za.ethClient)
if err != nil {
log.Errorf("error instantiating SpaceContractGoerli. Error: %v", err)
return nil, err
}
za.spaceContract = goerli
default:
errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId)
errMsg := fmt.Sprintf("unsupported chain id: %d", za.chainId)
log.Error(errMsg)
return nil, errors.New(errMsg)
}
@ -61,19 +50,6 @@ func NewZionAuthorizationV2(chainId int, ethClient *ethclient.Client, store Stor
return za, 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 *ZionAuthorizationV2) IsAllowed(args authorization.AuthorizationArgs) (bool, error) {
userIdentifier := CreateUserIdentifier(args.UserId)
@ -85,110 +61,54 @@ func (za *ZionAuthorizationV2) IsAllowed(args authorization.AuthorizationArgs) (
return true, nil
}
switch za.chainId {
case 1337, 31337:
isAllowed, err := za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission)
return isAllowed, err
// Check if user is entitled to space / channel.
switch roomInfo.RoomType {
case Space:
isEntitled, err := za.isEntitledToSpace(roomInfo, userIdentifier.AccountAddress, args.Permission)
return isEntitled, err
case Channel:
isEntitled, err := za.isEntitledToChannel(roomInfo, userIdentifier.AccountAddress, args.Permission)
return isEntitled, err
default:
errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId)
errMsg := fmt.Sprintf("unhandled room type: %s", roomInfo.RoomType)
log.Error("IsAllowed", errMsg)
return false, errors.New(errMsg)
}
}
func (za *ZionAuthorizationV2) getSpaceLocalhost(networkId string) (*localhost_space.LocalhostSpace, error) {
if za.localhostSpaces[networkId] == nil {
// convert the networkId to keccak256 spaceIdHash
spaceIdHash := NetworkIdToHash(networkId)
// then use the spaceFactory to fetch the space address
spaceAddress, err := za.localhostSpaceFactory.SpaceByHash(nil, spaceIdHash)
if err != nil {
return nil, err
}
// cache the space for future use
space, err := localhost_space.NewLocalhostSpace(spaceAddress, za.ethClient)
if err != nil {
return nil, err
}
za.localhostSpaces[networkId] = space
}
return za.localhostSpaces[networkId], nil
}
func (za *ZionAuthorizationV2) isSpaceOrChannelDisabledLocalhost(roomInfo RoomInfo) (bool, error) {
if za.localhostSpaceFactory == nil {
return false, errors.New("error fetching localhost space factory contract")
}
space, err := za.getSpaceLocalhost(roomInfo.SpaceNetworkId)
func (za *ZionAuthorizationV2) isEntitledToSpace(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) {
// space disabled check.
isDisabled, err := za.spaceContract.IsSpaceDisabled(roomInfo.SpaceNetworkId)
if err != nil {
return false, err
}
if space == nil {
errMsg := fmt.Sprintf("error fetching localhost space contract for %s", roomInfo.SpaceNetworkId)
return false, errors.New(errMsg)
}
switch roomInfo.ChannelNetworkId {
case "":
isDisabled, err := space.Disabled(nil)
return isDisabled, err
default:
channelIdHash := NetworkIdToHash(roomInfo.ChannelNetworkId)
channel, err := space.GetChannelByHash(nil, channelIdHash)
if err != nil {
return false, err
}
return channel.Disabled, err
}
}
func (za *ZionAuthorizationV2) isAllowedLocalhost(
roomInfo RoomInfo,
user common.Address,
permission authorization.Permission,
) (bool, error) {
if za.localhostSpaceFactory == nil {
return false, errors.New("localhost SpaceFactory is not initialised")
}
// check if space / channel is disabled.
disabled, err := za.isSpaceOrChannelDisabledLocalhost(roomInfo)
if disabled {
} else if isDisabled {
return false, ErrSpaceDisabled
} else if err != nil {
return false, err
}
// get the space and check if user is entitled.
space, err := za.getSpaceLocalhost(roomInfo.SpaceNetworkId)
// space entitlement check.
isEntitled, err := za.spaceContract.IsEntitledToSpace(
roomInfo.SpaceNetworkId,
user,
permission,
)
return isEntitled, err
}
func (za *ZionAuthorizationV2) isEntitledToChannel(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) {
// channel disabled check.
isDisabled, err := za.spaceContract.IsChannelDisabled(roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId)
if err != nil {
return false, err
} else if isDisabled {
return false, ErrSpaceDisabled
}
isEntitled := false // default to false always.
switch roomInfo.ChannelNetworkId {
case "":
// ChannelNetworkId is empty. Space entitlement check.
isEntitled, err = space.IsEntitledToSpace(
nil,
user,
permission.String(),
)
if err != nil {
return false, err
}
default:
// channel entitlement check
isEntitled, err = space.IsEntitledToChannel(
nil,
roomInfo.ChannelNetworkId,
user,
permission.String(),
)
if err != nil {
return false, err
}
}
return isEntitled, nil
// channel entitlement check.
isEntitled, err := za.spaceContract.IsEntitledToChannel(
roomInfo.SpaceNetworkId,
roomInfo.ChannelNetworkId,
user,
permission,
)
return isEntitled, err
}