mirror of
https://github.com/status-im/status-go.git
synced 2025-01-09 14:16:21 +00:00
38308d48f2
* feat_: log error and stacktrace when panic in goroutine * test_: add test TestSafeGo * chore_: rename logAndCall to call * chore_: rename SafeGo to Go * chore_: make lint-fix * chore_: use t.Cleanup * chore_: Revert "chore_: use t.Cleanup" This reverts commit 4eb420d179cc0e208e84c13cb941e6b3d1ed9819. * chore_: Revert "chore_: make lint-fix" This reverts commit fcc995f157e671a4229b47419c3a0e4004b5fdab. * chore_: Revert "chore_: rename SafeGo to Go" This reverts commit a6d73d6df583f313032d79aac62f66328039cb55. * chore_: Revert "chore_: rename logAndCall to call" This reverts commit 8fbe993bedb9fbba67349a44f151e2dd5e3bc4cc. * chore_: Revert "test_: add test TestSafeGo" This reverts commit a1fa91839f3960398980c6bf456e6462ec944819. * chore_: Revert "feat_: log error and stacktrace when panic in goroutine" This reverts commit f612dd828fa2ce410d0e806fe773ecbe3e86a68a. * feat_: log error and stacktrace when panic in goroutine * chore_: make lint-fix * chore_: rename logAndCall to call * chore_: renaming LogOnPanic * chore_: update rest goroutine function calls * chore_: make lint-fix
118 lines
3.1 KiB
Go
118 lines
3.1 KiB
Go
package ens
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/elliptic"
|
|
"encoding/hex"
|
|
"math/big"
|
|
"time"
|
|
|
|
ens "github.com/wealdtech/go-ens/v3"
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
|
|
gocommon "github.com/status-im/status-go/common"
|
|
"github.com/status-im/status-go/eth-node/crypto"
|
|
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
|
)
|
|
|
|
const (
|
|
contractQueryTimeout = 5000 * time.Millisecond
|
|
)
|
|
|
|
type Verifier struct {
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewVerifier returns a Verifier attached to the specified logger
|
|
func NewVerifier(logger *zap.Logger) *Verifier {
|
|
return &Verifier{logger: logger}
|
|
}
|
|
|
|
func (m *Verifier) ReverseResolve(address common.Address, rpcEndpoint string) (string, error) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), contractQueryTimeout)
|
|
defer cancel()
|
|
|
|
ethClient, err := ethclient.DialContext(ctx, rpcEndpoint)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return ens.ReverseResolve(ethClient, address)
|
|
}
|
|
|
|
func (m *Verifier) verifyENSName(ensInfo enstypes.ENSDetails, ethclient *ethclient.Client) enstypes.ENSResponse {
|
|
publicKeyStr := ensInfo.PublicKeyString
|
|
ensName := ensInfo.Name
|
|
m.logger.Info("Resolving ENS name", zap.String("name", ensName), zap.String("publicKey", publicKeyStr))
|
|
response := enstypes.ENSResponse{
|
|
Name: ensName,
|
|
PublicKeyString: publicKeyStr,
|
|
VerifiedAt: time.Now().Unix(),
|
|
}
|
|
|
|
expectedPubKeyBytes, err := hex.DecodeString(publicKeyStr)
|
|
if err != nil {
|
|
response.Error = err
|
|
return response
|
|
}
|
|
|
|
publicKey, err := crypto.UnmarshalPubkey(expectedPubKeyBytes)
|
|
if err != nil {
|
|
response.Error = err
|
|
return response
|
|
}
|
|
|
|
// Resolve ensName
|
|
resolver, err := ens.NewResolver(ethclient, ensName)
|
|
if err != nil {
|
|
m.logger.Error("error while creating ENS name resolver", zap.String("ensName", ensName), zap.Error(err))
|
|
response.Error = err
|
|
return response
|
|
}
|
|
x, y, err := resolver.PubKey()
|
|
if err != nil {
|
|
m.logger.Error("error while resolving public key from ENS name", zap.String("ensName", ensName), zap.Error(err))
|
|
response.Error = err
|
|
return response
|
|
}
|
|
|
|
// Assemble the bytes returned for the pubkey
|
|
pubKeyBytes := elliptic.Marshal(crypto.S256(), new(big.Int).SetBytes(x[:]), new(big.Int).SetBytes(y[:]))
|
|
|
|
response.PublicKey = publicKey
|
|
response.Verified = bytes.Equal(pubKeyBytes, expectedPubKeyBytes)
|
|
return response
|
|
}
|
|
|
|
// CheckBatch verifies that a registered ENS name matches the expected public key
|
|
func (m *Verifier) CheckBatch(ensDetails []enstypes.ENSDetails, rpcEndpoint, contractAddress string) (map[string]enstypes.ENSResponse, error) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), contractQueryTimeout)
|
|
defer cancel()
|
|
|
|
ch := make(chan enstypes.ENSResponse)
|
|
response := make(map[string]enstypes.ENSResponse)
|
|
|
|
ethclient, err := ethclient.DialContext(ctx, rpcEndpoint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, ensInfo := range ensDetails {
|
|
go func(info enstypes.ENSDetails) {
|
|
defer gocommon.LogOnPanic()
|
|
ch <- m.verifyENSName(info, ethclient)
|
|
}(ensInfo)
|
|
}
|
|
|
|
for range ensDetails {
|
|
r := <-ch
|
|
response[r.PublicKeyString] = r
|
|
}
|
|
close(ch)
|
|
|
|
return response, nil
|
|
}
|