From 92a622d6fbf754e320203ab551c5be9b21b1ef85 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Tue, 23 Aug 2022 08:29:30 -0400 Subject: [PATCH] feat: obtain ENSUsername address from registry (#2792) --- contracts/contracts.go | 7 +-- contracts/registrar/address.go | 23 -------- node/status_node_services.go | 5 ++ services/ens/api.go | 104 +++++++++++++++++++++++++++++---- services/ens/service.go | 1 + 5 files changed, 101 insertions(+), 39 deletions(-) delete mode 100644 contracts/registrar/address.go diff --git a/contracts/contracts.go b/contracts/contracts.go index c69cb4842..7ede5bfe5 100644 --- a/contracts/contracts.go +++ b/contracts/contracts.go @@ -40,12 +40,7 @@ func (c *ContractMaker) NewPublicResolver(chainID uint64, resolverAddress *commo return resolver.NewPublicResolver(*resolverAddress, backend) } -func (c *ContractMaker) NewUsernameRegistrar(chainID uint64) (*registrar.UsernameRegistrar, error) { - contractAddr, err := registrar.ContractAddress(chainID) - if err != nil { - return nil, err - } - +func (c *ContractMaker) NewUsernameRegistrar(chainID uint64, contractAddr common.Address) (*registrar.UsernameRegistrar, error) { backend, err := c.RPCClient.EthClient(chainID) if err != nil { return nil, err diff --git a/contracts/registrar/address.go b/contracts/registrar/address.go deleted file mode 100644 index 0d8937e9c..000000000 --- a/contracts/registrar/address.go +++ /dev/null @@ -1,23 +0,0 @@ -package registrar - -import ( - "errors" - - "github.com/ethereum/go-ethereum/common" -) - -var errorNotAvailableOnChainID = errors.New("not available for chainID") - -var contractAddressByChainID = map[uint64]common.Address{ - 1: common.HexToAddress("0xDB5ac1a559b02E12F29fC0eC0e37Be8E046DEF49"), // mainnet - 3: common.HexToAddress("0xdaae165beb8c06e0b7613168138ebba774aff071"), // ropsten - 5: common.HexToAddress("0xD1f7416F91E7Eb93dD96A61F12FC092aD6B67B11"), //goerli -} - -func ContractAddress(chainID uint64) (common.Address, error) { - addr, exists := contractAddressByChainID[chainID] - if !exists { - return *new(common.Address), errorNotAvailableOnChainID - } - return addr, nil -} diff --git a/node/status_node_services.go b/node/status_node_services.go index 7a2bf5b63..69e03e3a1 100644 --- a/node/status_node_services.go +++ b/node/status_node_services.go @@ -584,6 +584,11 @@ func (b *StatusNode) Cleanup() error { } } + err := b.ensSrvc.Stop() + if err != nil { + return err + } + return nil } diff --git a/services/ens/api.go b/services/ens/api.go index 6659f5588..ab0b22138 100644 --- a/services/ens/api.go +++ b/services/ens/api.go @@ -7,6 +7,7 @@ import ( "fmt" "math/big" "strings" + "sync" "github.com/ipfs/go-cid" "github.com/multiformats/go-multibase" @@ -20,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" "github.com/status-im/status-go/account" "github.com/status-im/status-go/contracts" "github.com/status-im/status-go/contracts/registrar" @@ -40,6 +42,9 @@ func NewAPI(rpcClient *rpc.Client, accountsManager *account.GethManager, rpcFilt accountsManager: accountsManager, rpcFiltersSrvc: rpcFiltersSrvc, config: config, + addrPerChain: make(map[uint64]common.Address), + + quit: make(chan struct{}), } } @@ -54,10 +59,22 @@ type API struct { accountsManager *account.GethManager rpcFiltersSrvc *rpcfilters.Service config *params.NodeConfig + + addrPerChain map[uint64]common.Address + addrPerChainMutex sync.Mutex + + quitOnce sync.Once + quit chan struct{} +} + +func (api *API) Stop() { + api.quitOnce.Do(func() { + close(api.quit) + }) } func (api *API) GetRegistrarAddress(ctx context.Context, chainID uint64) (common.Address, error) { - return registrar.ContractAddress(chainID) + return api.usernameRegistrarAddr(ctx, chainID) } func (api *API) Resolver(ctx context.Context, chainID uint64, username string) (*common.Address, error) { @@ -174,8 +191,65 @@ func (api *API) AddressOf(ctx context.Context, chainID uint64, username string) return &addr, nil } +func (api *API) usernameRegistrarAddr(ctx context.Context, chainID uint64) (common.Address, error) { + log.Info("obtaining username registrar address") + api.addrPerChainMutex.Lock() + defer api.addrPerChainMutex.Unlock() + + addr, ok := api.addrPerChain[chainID] + if ok { + return addr, nil + } + + registryAddr, err := api.OwnerOf(ctx, chainID, "stateofus.eth") + if err != nil { + return common.Address{}, err + } + + api.addrPerChain[chainID] = *registryAddr + + go func() { + registry, err := api.contractMaker.NewRegistry(chainID) + if err != nil { + return + } + + logs := make(chan *resolver.ENSRegistryWithFallbackNewOwner) + + sub, err := registry.WatchNewOwner(&bind.WatchOpts{}, logs, nil, nil) + if err != nil { + return + } + + for { + select { + case <-api.quit: + log.Info("quitting ens contract subscription") + sub.Unsubscribe() + return + case err := <-sub.Err(): + if err != nil { + log.Error("ens contract subscription error: " + err.Error()) + } + return + case vLog := <-logs: + api.addrPerChainMutex.Lock() + api.addrPerChain[chainID] = vLog.Owner + api.addrPerChainMutex.Unlock() + } + } + }() + + return *registryAddr, nil +} + func (api *API) ExpireAt(ctx context.Context, chainID uint64, username string) (string, error) { - registrar, err := api.contractMaker.NewUsernameRegistrar(chainID) + registryAddr, err := api.usernameRegistrarAddr(ctx, chainID) + if err != nil { + return "", err + } + + registrar, err := api.contractMaker.NewUsernameRegistrar(chainID, registryAddr) if err != nil { return "", err } @@ -190,7 +264,12 @@ func (api *API) ExpireAt(ctx context.Context, chainID uint64, username string) ( } func (api *API) Price(ctx context.Context, chainID uint64) (string, error) { - registrar, err := api.contractMaker.NewUsernameRegistrar(chainID) + registryAddr, err := api.usernameRegistrarAddr(ctx, chainID) + if err != nil { + return "", err + } + + registrar, err := api.contractMaker.NewUsernameRegistrar(chainID, registryAddr) if err != nil { return "", err } @@ -216,7 +295,12 @@ func (api *API) getSigner(chainID uint64, from types.Address, password string) b } func (api *API) Release(ctx context.Context, chainID uint64, txArgs transactions.SendTxArgs, password string, username string) (string, error) { - registrar, err := api.contractMaker.NewUsernameRegistrar(chainID) + registryAddr, err := api.usernameRegistrarAddr(ctx, chainID) + if err != nil { + return "", err + } + + registrar, err := api.contractMaker.NewUsernameRegistrar(chainID, registryAddr) if err != nil { return "", err } @@ -247,14 +331,14 @@ func (api *API) ReleaseEstimate(ctx context.Context, chainID uint64, txArgs tran return 0, err } - registrarAddress, err := registrar.ContractAddress(chainID) + registryAddr, err := api.usernameRegistrarAddr(ctx, chainID) if err != nil { return 0, err } return ethClient.EstimateGas(ctx, ethereum.CallMsg{ From: common.Address(txArgs.From), - To: ®istrarAddress, + To: ®istryAddr, Value: big.NewInt(0), Data: data, }) @@ -284,7 +368,7 @@ func (api *API) Register(ctx context.Context, chainID uint64, txArgs transaction return "", err } - registrarAddress, err := registrar.ContractAddress(chainID) + registryAddr, err := api.usernameRegistrarAddr(ctx, chainID) if err != nil { return "", err } @@ -292,7 +376,7 @@ func (api *API) Register(ctx context.Context, chainID uint64, txArgs transaction txOpts := txArgs.ToTransactOpts(api.getSigner(chainID, txArgs.From, password)) tx, err := snt.ApproveAndCall( txOpts, - registrarAddress, + registryAddr, price, extraData, ) @@ -329,12 +413,12 @@ func (api *API) RegisterPrepareTxCallMsg(ctx context.Context, chainID uint64, tx return ethereum.CallMsg{}, err } - registrarAddress, err := registrar.ContractAddress(chainID) + registryAddr, err := api.usernameRegistrarAddr(ctx, chainID) if err != nil { return ethereum.CallMsg{}, err } - data, err := sntABI.Pack("approveAndCall", registrarAddress, price, extraData) + data, err := sntABI.Pack("approveAndCall", registryAddr, price, extraData) if err != nil { return ethereum.CallMsg{}, err } diff --git a/services/ens/service.go b/services/ens/service.go index 9894ea0c0..1d1d6abe4 100644 --- a/services/ens/service.go +++ b/services/ens/service.go @@ -36,6 +36,7 @@ func (s *Service) Start() error { // Stop a service. func (s *Service) Stop() error { + s.api.Stop() return nil }