diff --git a/go.mod b/go.mod index e1be7176b9..06516ba0ce 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,9 @@ go 1.21 replace github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220224222438-c78f6963a1c0+incompatible require ( + github.com/Microsoft/go-winio v0.6.1 github.com/andybalholm/brotli v1.1.0 + github.com/deckarep/golang-set/v2 v2.6.0 github.com/dgraph-io/ristretto v0.1.1 github.com/docker/docker v25.0.4+incompatible github.com/docker/go-connections v0.5.0 @@ -17,14 +19,18 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/go-kit/kit v0.13.0 github.com/go-sql-driver/mysql v1.8.0 + github.com/gofrs/flock v0.8.1 github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.1 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/holiman/uint256 v1.2.4 + github.com/jolestar/go-commons-pool/v2 v2.1.2 github.com/mattn/go-sqlite3 v1.14.22 github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/pkg/errors v0.9.1 + github.com/rs/cors v1.10.1 github.com/sanity-io/litter v1.5.5 github.com/status-im/keycard-go v0.3.2 github.com/stretchr/testify v1.9.0 @@ -43,7 +49,6 @@ require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/DataDog/zstd v1.5.5 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/allegro/bigcache v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -65,7 +70,6 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect @@ -86,9 +90,7 @@ require ( github.com/go-playground/validator/v10 v10.19.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/glog v1.2.0 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -105,11 +107,8 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/pointerstructure v1.2.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -127,8 +126,6 @@ require ( github.com/prometheus/procfs v0.13.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.10.1 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/stretchr/objx v0.5.2 // indirect diff --git a/go.sum b/go.sum index 4f122dede7..f1251d5bde 100644 --- a/go.sum +++ b/go.sum @@ -128,6 +128,8 @@ github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -260,6 +262,8 @@ github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0Gqw github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jolestar/go-commons-pool/v2 v2.1.2 h1:E+XGo58F23t7HtZiC/W6jzO2Ux2IccSH/yx4nD+J1CM= +github.com/jolestar/go-commons-pool/v2 v2.1.2/go.mod h1:r4NYccrkS5UqP1YQI1COyTZ9UjPJAAGTUxzcsK1kqhY= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -309,7 +313,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -322,7 +325,6 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= @@ -398,6 +400,7 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -577,7 +580,6 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/go/common/log_events.go b/go/common/log_events.go index fd01b0357c..962762dbcf 100644 --- a/go/common/log_events.go +++ b/go/common/log_events.go @@ -1,7 +1,15 @@ package common import ( + "encoding/json" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ten-protocol/go-ten/go/common/viewingkey" @@ -14,7 +22,7 @@ type LogSubscription struct { ViewingKey *viewingkey.RPCSignedViewingKey // A subscriber-defined filter to apply to the stream of logs. - Filter *filters.FilterCriteria + Filter *FilterCriteriaJSON } // IDAndEncLog pairs an encrypted log with the ID of the subscription that generated it. @@ -36,6 +44,177 @@ type FilterCriteriaJSON struct { BlockHash *common.Hash `json:"blockHash"` FromBlock *rpc.BlockNumber `json:"fromBlock"` ToBlock *rpc.BlockNumber `json:"toBlock"` - Addresses interface{} `json:"address"` - Topics []interface{} `json:"topics"` + Addresses []common.Address `json:"addresses"` + Topics [][]common.Hash `json:"topics"` +} + +func FromCriteria(crit FilterCriteria) FilterCriteriaJSON { + var from *rpc.BlockNumber + if crit.FromBlock != nil { + f := (rpc.BlockNumber)(crit.FromBlock.Int64()) + from = &f + } + + var to *rpc.BlockNumber + if crit.ToBlock != nil { + t := (rpc.BlockNumber)(crit.ToBlock.Int64()) + to = &t + } + + return FilterCriteriaJSON{ + BlockHash: crit.BlockHash, + FromBlock: from, + ToBlock: to, + Addresses: crit.Addresses, + Topics: crit.Topics, + } +} + +func ToCriteria(jsonCriteria FilterCriteriaJSON) filters.FilterCriteria { + var from *big.Int + if jsonCriteria.FromBlock != nil { + from = big.NewInt(jsonCriteria.FromBlock.Int64()) + } + var to *big.Int + if jsonCriteria.ToBlock != nil { + to = big.NewInt(jsonCriteria.ToBlock.Int64()) + } + + return filters.FilterCriteria{ + BlockHash: jsonCriteria.BlockHash, + FromBlock: from, + ToBlock: to, + Addresses: jsonCriteria.Addresses, + Topics: jsonCriteria.Topics, + } +} + +var errInvalidTopic = errors.New("invalid topic(s)") + +// FilterCriteria represents a request to create a new filter. +// Same as ethereum.FilterQuery but with UnmarshalJSON() method. +// duplicated from geth to tweak the unmarshalling +type FilterCriteria ethereum.FilterQuery + +// UnmarshalJSON sets *args fields with given data. +func (args *FilterCriteria) UnmarshalJSON(data []byte) error { + type input struct { + BlockHash *common.Hash `json:"blockHash"` + FromBlock *rpc.BlockNumber `json:"fromBlock"` + ToBlock *rpc.BlockNumber `json:"toBlock"` + Addresses interface{} `json:"address"` + Topics []interface{} `json:"topics"` + } + + var raw input + if err := json.Unmarshal(data, &raw); err != nil { + // tweak to handle the case when an empty array is passed in by javascript libraries + if strings.Contains(err.Error(), "cannot unmarshal array") { + return nil + } + return err + } + + if raw.BlockHash != nil { + if raw.FromBlock != nil || raw.ToBlock != nil { + // BlockHash is mutually exclusive with FromBlock/ToBlock criteria + return errors.New("cannot specify both BlockHash and FromBlock/ToBlock, choose one or the other") + } + args.BlockHash = raw.BlockHash + } else { + if raw.FromBlock != nil { + args.FromBlock = big.NewInt(raw.FromBlock.Int64()) + } + + if raw.ToBlock != nil { + args.ToBlock = big.NewInt(raw.ToBlock.Int64()) + } + } + + args.Addresses = []common.Address{} + + if raw.Addresses != nil { + // raw.Address can contain a single address or an array of addresses + switch rawAddr := raw.Addresses.(type) { + case []interface{}: + for i, addr := range rawAddr { + if strAddr, ok := addr.(string); ok { + addr, err := decodeAddress(strAddr) + if err != nil { + return fmt.Errorf("invalid address at index %d: %v", i, err) + } + args.Addresses = append(args.Addresses, addr) + } else { + return fmt.Errorf("non-string address at index %d", i) + } + } + case string: + addr, err := decodeAddress(rawAddr) + if err != nil { + return fmt.Errorf("invalid address: %v", err) + } + args.Addresses = []common.Address{addr} + default: + return errors.New("invalid addresses in query") + } + } + + // topics is an array consisting of strings and/or arrays of strings. + // JSON null values are converted to common.Hash{} and ignored by the filter manager. + if len(raw.Topics) > 0 { + args.Topics = make([][]common.Hash, len(raw.Topics)) + for i, t := range raw.Topics { + switch topic := t.(type) { + case nil: + // ignore topic when matching logs + + case string: + // match specific topic + top, err := decodeTopic(topic) + if err != nil { + return err + } + args.Topics[i] = []common.Hash{top} + + case []interface{}: + // or case e.g. [null, "topic0", "topic1"] + for _, rawTopic := range topic { + if rawTopic == nil { + // null component, match all + args.Topics[i] = nil + break + } + if topic, ok := rawTopic.(string); ok { + parsed, err := decodeTopic(topic) + if err != nil { + return err + } + args.Topics[i] = append(args.Topics[i], parsed) + } else { + return errInvalidTopic + } + } + default: + return errInvalidTopic + } + } + } + + return nil +} + +func decodeAddress(s string) (common.Address, error) { + b, err := hexutil.Decode(s) + if err == nil && len(b) != common.AddressLength { + err = fmt.Errorf("hex has invalid length %d after decoding; expected %d for address", len(b), common.AddressLength) + } + return common.BytesToAddress(b), err +} + +func decodeTopic(s string) (common.Hash, error) { + b, err := hexutil.Decode(s) + if err == nil && len(b) != common.HashLength { + err = fmt.Errorf("hex has invalid length %d after decoding; expected %d for topic", len(b), common.HashLength) + } + return common.BytesToHash(b), err } diff --git a/go/common/viewingkey/viewing_key.go b/go/common/viewingkey/viewing_key.go index 6d70a59977..93ad049999 100644 --- a/go/common/viewingkey/viewing_key.go +++ b/go/common/viewingkey/viewing_key.go @@ -42,7 +42,7 @@ func GenerateViewingKeyForWallet(wal wallet.Wallet) (*ViewingKey, error) { if err != nil { return nil, err } - encryptionToken := CalculateUserIDHex(crypto.CompressPubkey(viewingPrivateKeyECIES.PublicKey.ExportECDSA())) + encryptionToken := CalculateUserID(crypto.CompressPubkey(viewingPrivateKeyECIES.PublicKey.ExportECDSA())) messageToSign, err := GenerateMessage(encryptionToken, chainID, PersonalSignVersion, messageType) if err != nil { return nil, fmt.Errorf("failed to generate message for viewing key: %w", err) diff --git a/go/common/viewingkey/viewing_key_messages.go b/go/common/viewingkey/viewing_key_messages.go index 01ff4829e5..a0efcbc362 100644 --- a/go/common/viewingkey/viewing_key_messages.go +++ b/go/common/viewingkey/viewing_key_messages.go @@ -6,6 +6,8 @@ import ( "fmt" "math/big" + "github.com/status-im/keycard-go/hexutils" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" @@ -29,18 +31,13 @@ const ( EIP712EncryptionToken = "Encryption Token" EIP712DomainNameValue = "Ten" EIP712DomainVersionValue = "1.0" - UserIDHexLength = 40 + UserIDLength = 20 PersonalSignMessageFormat = "Token: %s on chain: %d version: %d" PersonalSignVersion = 1 ) -// EIP712EncryptionTokens is a list of all possible options for Encryption token name -var EIP712EncryptionTokens = [...]string{ - EIP712EncryptionToken, -} - type MessageGenerator interface { - generateMessage(encryptionToken string, chainID int64, version int) ([]byte, error) + generateMessage(encryptionToken []byte, chainID int64, version int) ([]byte, error) } type ( @@ -54,13 +51,13 @@ var messageGenerators = map[SignatureType]MessageGenerator{ } // GenerateMessage generates a message for the given encryptionToken, chainID, version and signatureType -func (p PersonalMessageGenerator) generateMessage(encryptionToken string, chainID int64, version int) ([]byte, error) { - return []byte(fmt.Sprintf(PersonalSignMessageFormat, encryptionToken, chainID, version)), nil +func (p PersonalMessageGenerator) generateMessage(encryptionToken []byte, chainID int64, version int) ([]byte, error) { + return []byte(fmt.Sprintf(PersonalSignMessageFormat, hexutils.BytesToHex(encryptionToken), chainID, version)), nil } -func (e EIP712MessageGenerator) generateMessage(encryptionToken string, chainID int64, _ int) ([]byte, error) { - if len(encryptionToken) != UserIDHexLength { - return nil, fmt.Errorf("userID hex length must be %d, received %d", UserIDHexLength, len(encryptionToken)) +func (e EIP712MessageGenerator) generateMessage(encryptionToken []byte, chainID int64, _ int) ([]byte, error) { + if len(encryptionToken) != UserIDLength { + return nil, fmt.Errorf("userID must be %d bytes, received %d", UserIDLength, len(encryptionToken)) } EIP712TypedData := createTypedDataForEIP712Message(encryptionToken, chainID) @@ -73,7 +70,7 @@ func (e EIP712MessageGenerator) generateMessage(encryptionToken string, chainID } // GenerateMessage generates a message for the given encryptionToken, chainID, version and signatureType -func GenerateMessage(encryptionToken string, chainID int64, version int, signatureType SignatureType) ([]byte, error) { +func GenerateMessage(encryptionToken []byte, chainID int64, version int, signatureType SignatureType) ([]byte, error) { generator, exists := messageGenerators[signatureType] if !exists { return nil, fmt.Errorf("unsupported signature type") @@ -144,8 +141,8 @@ func getBytesFromTypedData(typedData apitypes.TypedData) ([]byte, error) { } // createTypedDataForEIP712Message creates typed data for EIP712 message -func createTypedDataForEIP712Message(encryptionToken string, chainID int64) apitypes.TypedData { - encryptionToken = "0x" + encryptionToken +func createTypedDataForEIP712Message(encryptionToken []byte, chainID int64) apitypes.TypedData { + hexToken := hexutils.BytesToHex(encryptionToken) domain := apitypes.TypedDataDomain{ Name: EIP712DomainNameValue, @@ -154,7 +151,7 @@ func createTypedDataForEIP712Message(encryptionToken string, chainID int64) apit } message := map[string]interface{}{ - EIP712EncryptionToken: encryptionToken, + EIP712EncryptionToken: hexToken, } types := apitypes.Types{ diff --git a/go/common/viewingkey/viewing_key_signature.go b/go/common/viewingkey/viewing_key_signature.go index 6737b5c574..38eb822f95 100644 --- a/go/common/viewingkey/viewing_key_signature.go +++ b/go/common/viewingkey/viewing_key_signature.go @@ -13,7 +13,7 @@ import ( // SignatureChecker is an interface for checking // if signature is valid for provided encryptionToken and chainID and return singing address or nil if not valid type SignatureChecker interface { - CheckSignature(encryptionToken string, signature []byte, chainID int64) (*gethcommon.Address, error) + CheckSignature(encryptionToken []byte, signature []byte, chainID int64) (*gethcommon.Address, error) } type ( @@ -22,7 +22,7 @@ type ( ) // CheckSignature checks if signature is valid for provided encryptionToken and chainID and return address or nil if not valid -func (psc PersonalSignChecker) CheckSignature(encryptionToken string, signature []byte, chainID int64) (*gethcommon.Address, error) { +func (psc PersonalSignChecker) CheckSignature(encryptionToken []byte, signature []byte, chainID int64) (*gethcommon.Address, error) { if len(signature) != 65 { return nil, fmt.Errorf("invalid signaure length: %d", len(signature)) } @@ -51,7 +51,7 @@ func (psc PersonalSignChecker) CheckSignature(encryptionToken string, signature return nil, fmt.Errorf("signature verification failed") } -func (e EIP712Checker) CheckSignature(encryptionToken string, signature []byte, chainID int64) (*gethcommon.Address, error) { +func (e EIP712Checker) CheckSignature(encryptionToken []byte, signature []byte, chainID int64) (*gethcommon.Address, error) { if len(signature) != 65 { return nil, fmt.Errorf("invalid signaure length: %d", len(signature)) } @@ -88,7 +88,7 @@ var signatureCheckers = map[SignatureType]SignatureChecker{ } // CheckSignature checks if signature is valid for provided encryptionToken and chainID and return address or nil if not valid -func CheckSignature(encryptionToken string, signature []byte, chainID int64, signatureType SignatureType) (*gethcommon.Address, error) { +func CheckSignature(encryptionToken []byte, signature []byte, chainID int64, signatureType SignatureType) (*gethcommon.Address, error) { checker, exists := signatureCheckers[signatureType] if !exists { return nil, fmt.Errorf("unsupported signature type") diff --git a/go/enclave/events/subscription_manager.go b/go/enclave/events/subscription_manager.go index fcaeaaeb2e..b49ff1f84e 100644 --- a/go/enclave/events/subscription_manager.go +++ b/go/enclave/events/subscription_manager.go @@ -3,7 +3,6 @@ package events import ( "encoding/json" "fmt" - "math/big" "sync" "github.com/ten-protocol/go-ten/go/enclave/vkhandler" @@ -19,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" gethlog "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" "github.com/ten-protocol/go-ten/go/common" ) @@ -61,7 +59,7 @@ func NewSubscriptionManager(storage storage.Storage, chainID int64, logger gethl // correctly. If there is an existing subscription with the given ID, it is overwritten. func (s *SubscriptionManager) AddSubscription(id gethrpc.ID, encodedSubscription []byte) error { subscription := &common.LogSubscription{} - if err := rlp.DecodeBytes(encodedSubscription, subscription); err != nil { + if err := json.Unmarshal(encodedSubscription, subscription); err != nil { return fmt.Errorf("could not decocde log subscription from RLP. Cause: %w", err) } @@ -238,15 +236,15 @@ func getUserAddrsFromLogTopics(log *types.Log, db *state.StateDB) []*gethcommon. // Lifted from eth/filters/filter.go in the go-ethereum repository. // filterLogs creates a slice of logs matching the given criteria. -func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []gethcommon.Address, topics [][]gethcommon.Hash, logger gethlog.Logger) []*types.Log { //nolint:gocognit +func filterLogs(logs []*types.Log, fromBlock, toBlock *gethrpc.BlockNumber, addresses []gethcommon.Address, topics [][]gethcommon.Hash, logger gethlog.Logger) []*types.Log { //nolint:gocognit var ret []*types.Log Logs: for _, logItem := range logs { - if fromBlock != nil && fromBlock.Int64() >= 0 && fromBlock.Uint64() > logItem.BlockNumber { + if fromBlock != nil && fromBlock.Int64() >= 0 && fromBlock.Int64() > int64(logItem.BlockNumber) { logger.Debug("Skipping log ", "log", logItem, "reason", "In the past. The starting block num for filter is bigger than log") continue } - if toBlock != nil && toBlock.Int64() > 0 && toBlock.Uint64() < logItem.BlockNumber { + if toBlock != nil && toBlock.Int64() > 0 && toBlock.Int64() < int64(logItem.BlockNumber) { logger.Debug("Skipping log ", "log", logItem, "reason", "In the future. The ending block num for filter is smaller than log") continue } diff --git a/go/enclave/rpc/GetBalance.go b/go/enclave/rpc/GetBalance.go index de9b6a4f42..8bdc26fc14 100644 --- a/go/enclave/rpc/GetBalance.go +++ b/go/enclave/rpc/GetBalance.go @@ -3,6 +3,8 @@ package rpc import ( "fmt" + "github.com/status-im/keycard-go/hexutils" + "github.com/ethereum/go-ethereum/common" "github.com/ten-protocol/go-ten/lib/gethfork/rpc" @@ -48,7 +50,7 @@ func GetBalanceExecute(builder *CallBuilder[BalanceReq, hexutil.Big], rpc *Encry // authorise the call if acctOwner.Hex() != builder.VK.AccountAddress.Hex() { - rpc.logger.Debug("Unauthorised call", "address", acctOwner, "vk", builder.VK.AccountAddress, "userId", builder.VK.UserID) + rpc.logger.Debug("Unauthorised call", "address", acctOwner, "vk", builder.VK.AccountAddress, "userId", hexutils.BytesToHex(builder.VK.UserID)) builder.Status = NotAuthorised return nil } diff --git a/go/enclave/rpc/GetLogs.go b/go/enclave/rpc/GetLogs.go index 9ac1d2acbc..b4798600e2 100644 --- a/go/enclave/rpc/GetLogs.go +++ b/go/enclave/rpc/GetLogs.go @@ -5,39 +5,40 @@ import ( "errors" "fmt" + "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/errutil" "github.com/ethereum/go-ethereum/core/types" - gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ten-protocol/go-ten/go/common/syserr" ) func GetLogsValidate(reqParams []any, builder *CallBuilder[filters.FilterCriteria, []*types.Log], _ *EncryptionManager) error { - // Parameters are [Filter, Address] - if len(reqParams) != 2 { + // Parameters are [Filter] + if len(reqParams) != 1 { builder.Err = fmt.Errorf("unexpected number of parameters") return nil } - // We extract the arguments from the param bytes. - filter, forAddress, err := extractGetLogsParams(reqParams) + + serialised, err := json.Marshal(reqParams[0]) if err != nil { - builder.Err = err - return nil //nolint:nilerr + builder.Err = fmt.Errorf("invalid parameter %w", err) + return nil + } + var crit common.FilterCriteriaJSON + err = json.Unmarshal(serialised, &crit) + if err != nil { + builder.Err = fmt.Errorf("invalid parameter %w", err) + return nil } - builder.From = forAddress - builder.Param = filter + filter := common.ToCriteria(crit) + + builder.Param = &filter return nil } func GetLogsExecute(builder *CallBuilder[filters.FilterCriteria, []*types.Log], rpc *EncryptionManager) error { //nolint:gocognit - err := authenticateFrom(builder.VK, builder.From) - if err != nil { - builder.Err = err - return nil //nolint:nilerr - } - filter := builder.Param // todo logic to check that the filter is valid // can't have both from and blockhash @@ -83,7 +84,7 @@ func GetLogsExecute(builder *CallBuilder[filters.FilterCriteria, []*types.Log], } // We retrieve the relevant logs that match the filter. - filteredLogs, err := rpc.storage.FilterLogs(builder.From, from, to, nil, filter.Addresses, filter.Topics) + filteredLogs, err := rpc.storage.FilterLogs(builder.VK.AccountAddress, from, to, nil, filter.Addresses, filter.Topics) if err != nil { if errors.Is(err, syserr.InternalError{}) { return err @@ -95,28 +96,3 @@ func GetLogsExecute(builder *CallBuilder[filters.FilterCriteria, []*types.Log], builder.ReturnValue = &filteredLogs return nil } - -// Returns the params extracted from an eth_getLogs request. -func extractGetLogsParams(paramList []interface{}) (*filters.FilterCriteria, *gethcommon.Address, error) { - // We extract the first param, the filter for the logs. - // We marshal the filter criteria from a map to JSON, then back from JSON into a FilterCriteria. This is - // because the filter criteria arrives as a map, and there is no way to convert it to a map directly into a - // FilterCriteria. - filterJSON, err := json.Marshal(paramList[0]) - if err != nil { - return nil, nil, fmt.Errorf("could not marshal filter criteria to JSON. Cause: %w", err) - } - filter := filters.FilterCriteria{} - err = filter.UnmarshalJSON(filterJSON) - if err != nil { - return nil, nil, fmt.Errorf("could not unmarshal filter criteria from JSON. Cause: %w", err) - } - - // We extract the second param, the address the logs are for. - forAddressHex, ok := paramList[1].(string) - if !ok { - return nil, nil, fmt.Errorf("expected second argument in GetLogs request to be of type string, but got %T", paramList[0]) - } - forAddress := gethcommon.HexToAddress(forAddressHex) - return &filter, &forAddress, nil -} diff --git a/go/enclave/vkhandler/vk_handler.go b/go/enclave/vkhandler/vk_handler.go index 06d6d27335..e1ec0bf4f8 100644 --- a/go/enclave/vkhandler/vk_handler.go +++ b/go/enclave/vkhandler/vk_handler.go @@ -1,4 +1,4 @@ -package vkhandler +package vkhandler //nolint:typecheck import ( "crypto/rand" @@ -21,7 +21,7 @@ type AuthenticatedViewingKey struct { rpcVK *viewingkey.RPCSignedViewingKey AccountAddress *gethcommon.Address ecdsaKey *ecies.PublicKey - UserID string + UserID []byte } func VerifyViewingKey(rpcVK *viewingkey.RPCSignedViewingKey, chainID int64) (*AuthenticatedViewingKey, error) { @@ -48,7 +48,7 @@ func VerifyViewingKey(rpcVK *viewingkey.RPCSignedViewingKey, chainID int64) (*Au // checkViewingKeyAndRecoverAddress checks the signature and recovers the address from the viewing key func checkViewingKeyAndRecoverAddress(vk *AuthenticatedViewingKey, chainID int64) (*gethcommon.Address, error) { // get userID from viewingKey public key - userID := viewingkey.CalculateUserIDHex(vk.rpcVK.PublicKey) + userID := viewingkey.CalculateUserID(vk.rpcVK.PublicKey) vk.UserID = userID // check the signature and recover the address assuming the message was signed with EIP712 diff --git a/go/enclave/vkhandler/vk_handler_test.go b/go/enclave/vkhandler/vk_handler_test.go index e8065ef2e8..1e4704a0f9 100644 --- a/go/enclave/vkhandler/vk_handler_test.go +++ b/go/enclave/vkhandler/vk_handler_test.go @@ -18,14 +18,14 @@ const chainID = 443 // generateRandomUserKeys - // generates a random user private key and a random viewing key private key and returns the user private key, // the viewing key private key, the userID and the user address -func generateRandomUserKeys() (*ecdsa.PrivateKey, *ecdsa.PrivateKey, string, gethcommon.Address) { +func generateRandomUserKeys() (*ecdsa.PrivateKey, *ecdsa.PrivateKey, []byte, gethcommon.Address) { userPrivKey, err := crypto.GenerateKey() // user private key if err != nil { - return nil, nil, "", gethcommon.Address{} + return nil, nil, nil, gethcommon.Address{} } vkPrivKey, _ := crypto.GenerateKey() // viewingkey generated in the gateway if err != nil { - return nil, nil, "", gethcommon.Address{} + return nil, nil, nil, gethcommon.Address{} } // get the address from userPrivKey @@ -33,7 +33,7 @@ func generateRandomUserKeys() (*ecdsa.PrivateKey, *ecdsa.PrivateKey, string, get // get userID from viewingKey public key vkPubKeyBytes := crypto.CompressPubkey(ecies.ImportECDSAPublic(&vkPrivKey.PublicKey).ExportECDSA()) - userID := viewingkey.CalculateUserIDHex(vkPubKeyBytes) + userID := viewingkey.CalculateUserID(vkPubKeyBytes) return userPrivKey, vkPrivKey, userID, userAddress } diff --git a/go/obsclient/authclient.go b/go/obsclient/authclient.go index f417e3443f..6f4eec0495 100644 --- a/go/obsclient/authclient.go +++ b/go/obsclient/authclient.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/params" "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/viewingkey" @@ -192,13 +191,13 @@ func (ac *AuthObsClient) BalanceAt(ctx context.Context, blockNumber *big.Int) (* return (*big.Int)(&result), err } -func (ac *AuthObsClient) SubscribeFilterLogs(ctx context.Context, filterCriteria filters.FilterCriteria, ch chan common.IDAndLog) (ethereum.Subscription, error) { +func (ac *AuthObsClient) SubscribeFilterLogs(ctx context.Context, filterCriteria common.FilterCriteria, ch chan common.IDAndLog) (ethereum.Subscription, error) { return ac.rpcClient.Subscribe(ctx, nil, rpc.SubscribeNamespace, ch, rpc.SubscriptionTypeLogs, filterCriteria) } -func (ac *AuthObsClient) GetLogs(ctx context.Context, filterCriteria common.FilterCriteriaJSON) ([]*types.Log, error) { +func (ac *AuthObsClient) GetLogs(ctx context.Context, filterCriteria common.FilterCriteria) ([]*types.Log, error) { var result responses.LogsType - err := ac.rpcClient.CallContext(ctx, &result, rpc.GetLogs, filterCriteria, ac.account) + err := ac.rpcClient.CallContext(ctx, &result, rpc.GetLogs, filterCriteria) if err != nil { return nil, err } diff --git a/go/rpc/client.go b/go/rpc/client.go index cb2297ac20..78e52fb28a 100644 --- a/go/rpc/client.go +++ b/go/rpc/client.go @@ -33,8 +33,6 @@ const ( GetTotalTxs = "tenscan_getTotalTransactions" Attestation = "tenscan_attestation" StopHost = "test_stopHost" - Subscribe = "eth_subscribe" - Unsubscribe = "eth_unsubscribe" SubscribeNamespace = "eth" SubscriptionTypeLogs = "logs" diff --git a/go/rpc/encrypted_client.go b/go/rpc/encrypted_client.go index 24050814f2..8b0d8635e8 100644 --- a/go/rpc/encrypted_client.go +++ b/go/rpc/encrypted_client.go @@ -12,8 +12,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/rlp" "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/errutil" "github.com/ten-protocol/go-ten/go/common/log" @@ -70,6 +68,10 @@ func NewEncRPCClient(client Client, viewingKey *viewingkey.ViewingKey, logger ge return encClient, nil } +func (c *EncRPCClient) Client() Client { + return c.obscuroClient +} + // Call handles JSON rpc requests without a context - see CallContext for details func (c *EncRPCClient) Call(result interface{}, method string, args ...interface{}) error { return c.CallContext(nil, result, method, args...) //nolint:staticcheck @@ -108,8 +110,7 @@ func (c *EncRPCClient) Subscribe(ctx context.Context, _ interface{}, namespace s return nil, err } - // We use RLP instead of JSON marshaling here, as for some reason the filter criteria doesn't unmarshal correctly from JSON. - encodedLogSubscription, err := rlp.EncodeToBytes(logSubscription) + encodedLogSubscription, err := json.Marshal(logSubscription) if err != nil { return nil, err } @@ -181,20 +182,16 @@ func (c *EncRPCClient) createAuthenticatedLogSubscription(args []interface{}) (* // If there are less than two arguments, it means no filter criteria was passed. if len(args) < 2 { - logSubscription.Filter = &filters.FilterCriteria{} + logSubscription.Filter = &common.FilterCriteriaJSON{} return logSubscription, nil } - filterCriteria, ok := args[1].(filters.FilterCriteria) + filterCriteria, ok := args[1].(common.FilterCriteria) if !ok { return nil, fmt.Errorf("invalid subscription") } - // If we do not override a nil block hash to an empty one, RLP decoding will fail on the enclave side. - if filterCriteria.BlockHash == nil { - filterCriteria.BlockHash = &gethcommon.Hash{} - } - - logSubscription.Filter = &filterCriteria + fc := common.FromCriteria(filterCriteria) + logSubscription.Filter = &fc return logSubscription, nil } @@ -243,13 +240,13 @@ func (c *EncRPCClient) executeSensitiveCall(ctx context.Context, result interfac // EstimateGas and Call methods return EVM Errors that are json objects // and contain multiple keys that normally do not get serialized if method == EstimateGas || method == Call { - var result errutil.EVMSerialisableError - err = json.Unmarshal([]byte(decodedError.Error()), &result) + var evmErr errutil.EVMSerialisableError + err = json.Unmarshal([]byte(decodedError.Error()), &evmErr) if err != nil { - return err + return decodedError } // Return the evm user error. - return result + return evmErr } // Return the user error. diff --git a/go/rpc/network_client.go b/go/rpc/network_client.go index 22c9c4e64d..aa08c4274c 100644 --- a/go/rpc/network_client.go +++ b/go/rpc/network_client.go @@ -7,6 +7,7 @@ import ( "github.com/ten-protocol/go-ten/go/common/viewingkey" "github.com/ten-protocol/go-ten/lib/gethfork/rpc" + gethrpc "github.com/ten-protocol/go-ten/lib/gethfork/rpc" gethlog "github.com/ethereum/go-ethereum/log" ) @@ -16,9 +17,9 @@ const ( http = "http://" ) -// networkClient is a Client implementation that wraps Geth's rpc.Client to make calls to the obscuro node -type networkClient struct { - rpcClient *rpc.Client +// NetworkClient is a Client implementation that wraps Geth's rpc.Client to make calls to the obscuro node +type NetworkClient struct { + RpcClient *rpc.Client } // NewEncNetworkClient returns a network RPC client with Viewing Key encryption/decryption @@ -34,6 +35,14 @@ func NewEncNetworkClient(rpcAddress string, viewingKey *viewingkey.ViewingKey, l return encClient, nil } +func NewEncNetworkClientFromConn(connection *gethrpc.Client, viewingKey *viewingkey.ViewingKey, logger gethlog.Logger) (*EncRPCClient, error) { + encClient, err := NewEncRPCClient(&NetworkClient{RpcClient: connection}, viewingKey, logger) + if err != nil { + return nil, err + } + return encClient, nil +} + // NewNetworkClient returns a client that can make RPC calls to an Obscuro node func NewNetworkClient(address string) (Client, error) { if !strings.HasPrefix(address, http) && !strings.HasPrefix(address, ws) { @@ -45,25 +54,25 @@ func NewNetworkClient(address string) (Client, error) { return nil, fmt.Errorf("could not create RPC client on %s. Cause: %w", address, err) } - return &networkClient{ - rpcClient: rpcClient, + return &NetworkClient{ + RpcClient: rpcClient, }, nil } // Call handles JSON rpc requests, delegating to the geth RPC client // The result must be a pointer so that package json can unmarshal into it. You can also pass nil, in which case the result is ignored. -func (c *networkClient) Call(result interface{}, method string, args ...interface{}) error { - return c.rpcClient.Call(result, method, args...) +func (c *NetworkClient) Call(result interface{}, method string, args ...interface{}) error { + return c.RpcClient.Call(result, method, args...) } -func (c *networkClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - return c.rpcClient.CallContext(ctx, result, method, args...) +func (c *NetworkClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + return c.RpcClient.CallContext(ctx, result, method, args...) } -func (c *networkClient) Subscribe(ctx context.Context, _ interface{}, namespace string, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) { - return c.rpcClient.Subscribe(ctx, namespace, channel, args...) +func (c *NetworkClient) Subscribe(ctx context.Context, _ interface{}, namespace string, channel interface{}, args ...interface{}) (*gethrpc.ClientSubscription, error) { + return c.RpcClient.Subscribe(ctx, namespace, channel, args...) } -func (c *networkClient) Stop() { - c.rpcClient.Close() +func (c *NetworkClient) Stop() { + c.RpcClient.Close() } diff --git a/integration/constants.go b/integration/constants.go index 48b3bcfa29..e6c73d8224 100644 --- a/integration/constants.go +++ b/integration/constants.go @@ -12,11 +12,11 @@ const ( StartPortNetworkTests = 17000 StartPortSmartContractTests = 18000 StartPortContractDeployerTest1 = 19000 - StartPortContractDeployerTest2 = 20000 - StartPortWalletExtensionUnitTest = 21000 + StartPortContractDeployerTest2 = 21000 StartPortFaucetUnitTest = 22000 StartPortFaucetHTTPUnitTest = 23000 StartPortTenGatewayUnitTest = 24000 + StartPortWalletExtensionUnitTest = 25000 DefaultGethWSPortOffset = 100 DefaultGethAUTHPortOffset = 200 diff --git a/integration/networktest/env/network_setup.go b/integration/networktest/env/network_setup.go index 8f0b4df2ca..86d45bb8e7 100644 --- a/integration/networktest/env/network_setup.go +++ b/integration/networktest/env/network_setup.go @@ -8,8 +8,8 @@ import ( "github.com/ten-protocol/go-ten/integration" "github.com/ten-protocol/go-ten/integration/common/testlog" "github.com/ten-protocol/go-ten/integration/networktest" - gatewaycfg "github.com/ten-protocol/go-ten/tools/walletextension/config" - "github.com/ten-protocol/go-ten/tools/walletextension/container" + "github.com/ten-protocol/go-ten/tools/walletextension" + wecommon "github.com/ten-protocol/go-ten/tools/walletextension/common" ) const ( @@ -68,7 +68,7 @@ type TestnetEnvOption func(env *testnetEnv) type testnetEnv struct { testnetConnector *testnetConnector localTenGateway bool - tenGatewayContainer *container.WalletExtensionContainer + tenGatewayContainer *walletextension.Container logger gethlog.Logger } @@ -99,7 +99,7 @@ func (t *testnetEnv) startTenGateway() { validatorHTTP := validator[len("http://"):] // replace the last character with a 1 (expect it to be zero), this is good enough for these tests validatorWS := validatorHTTP[:len(validatorHTTP)-1] + "1" - cfg := gatewaycfg.Config{ + cfg := wecommon.Config{ WalletExtensionHost: "127.0.0.1", WalletExtensionPortHTTP: _gwHTTPPort, WalletExtensionPortWS: _gwWSPort, @@ -110,7 +110,7 @@ func (t *testnetEnv) startTenGateway() { DBType: "sqlite", TenChainID: integration.TenChainID, } - tenGWContainer := container.NewWalletExtensionContainerFromConfig(cfg, t.logger) + tenGWContainer := walletextension.NewContainerFromConfig(cfg, t.logger) go func() { fmt.Println("Starting Ten Gateway, HTTP Port:", _gwHTTPPort, "WS Port:", _gwWSPort) err := tenGWContainer.Start() diff --git a/integration/obscurogateway/errors_contract.go b/integration/obscurogateway/errors_contract.go index 105640d9ae..67e2c076ad 100644 --- a/integration/obscurogateway/errors_contract.go +++ b/integration/obscurogateway/errors_contract.go @@ -1,4 +1,4 @@ -package faucet +package obscurogateway import ( "strings" diff --git a/integration/obscurogateway/events_contract.go b/integration/obscurogateway/events_contract.go index 859472ca6d..2815f56f2b 100644 --- a/integration/obscurogateway/events_contract.go +++ b/integration/obscurogateway/events_contract.go @@ -1,4 +1,4 @@ -package faucet +package obscurogateway import ( "strings" diff --git a/integration/obscurogateway/gateway_user.go b/integration/obscurogateway/gateway_user.go index 3f425d351c..b37445c504 100644 --- a/integration/obscurogateway/gateway_user.go +++ b/integration/obscurogateway/gateway_user.go @@ -1,4 +1,4 @@ -package faucet +package obscurogateway import ( "context" @@ -22,7 +22,7 @@ type GatewayUser struct { tgClient *lib.TGLib } -func NewUser(wallets []wallet.Wallet, serverAddressHTTP string, serverAddressWS string) (*GatewayUser, error) { +func NewGatewayUser(wallets []wallet.Wallet, serverAddressHTTP string, serverAddressWS string) (*GatewayUser, error) { ogClient := lib.NewTenGatewayLibrary(serverAddressHTTP, serverAddressWS) // automatically join diff --git a/tools/walletextension/common/json.go b/integration/obscurogateway/json.go similarity index 96% rename from tools/walletextension/common/json.go rename to integration/obscurogateway/json.go index 2079aef3bc..41b8629f0c 100644 --- a/tools/walletextension/common/json.go +++ b/integration/obscurogateway/json.go @@ -1,4 +1,4 @@ -package common +package obscurogateway import ( "encoding/json" diff --git a/integration/obscurogateway/tengateway_test.go b/integration/obscurogateway/tengateway_test.go index 1dd7fc7d63..c8846dedfc 100644 --- a/integration/obscurogateway/tengateway_test.go +++ b/integration/obscurogateway/tengateway_test.go @@ -1,4 +1,4 @@ -package faucet +package obscurogateway import ( "bytes" @@ -12,8 +12,12 @@ import ( "testing" "time" + "github.com/ten-protocol/go-ten/lib/gethfork/rpc" + + "github.com/ten-protocol/go-ten/tools/walletextension" + "github.com/go-kit/kit/transport/http/jsonrpc" - "github.com/ten-protocol/go-ten/go/rpc" + tenrpc "github.com/ten-protocol/go-ten/go/rpc" log2 "github.com/ten-protocol/go-ten/go/common/log" @@ -38,8 +42,6 @@ import ( "github.com/ten-protocol/go-ten/integration/ethereummock" "github.com/ten-protocol/go-ten/integration/simulation/network" "github.com/ten-protocol/go-ten/integration/simulation/params" - "github.com/ten-protocol/go-ten/tools/walletextension/config" - "github.com/ten-protocol/go-ten/tools/walletextension/container" "github.com/ten-protocol/go-ten/tools/walletextension/lib" "github.com/valyala/fasthttp" ) @@ -61,7 +63,7 @@ func TestTenGateway(t *testing.T) { startPort := integration.StartPortTenGatewayUnitTest createTenNetwork(t, startPort) - tenGatewayConf := config.Config{ + tenGatewayConf := wecommon.Config{ WalletExtensionHost: "127.0.0.1", WalletExtensionPortHTTP: startPort + integration.DefaultTenGatewayHTTPPortOffset, WalletExtensionPortWS: startPort + integration.DefaultTenGatewayWSPortOffset, @@ -74,7 +76,7 @@ func TestTenGateway(t *testing.T) { StoreIncomingTxs: true, } - tenGwContainer := container.NewWalletExtensionContainerFromConfig(tenGatewayConf, testlog.Logger()) + tenGwContainer := walletextension.NewContainerFromConfig(tenGatewayConf, testlog.Logger()) go func() { err := tenGwContainer.Start() if err != nil { @@ -122,15 +124,18 @@ func TestTenGateway(t *testing.T) { } func testMultipleAccountsSubscription(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { - user0, err := NewUser([]wallet.Wallet{w}, httpURL, wsURL) + user0, err := NewGatewayUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) require.NoError(t, err) testlog.Logger().Info("Created user with encryption token", "t", user0.tgClient.UserID()) - user1, err := NewUser([]wallet.Wallet{datagenerator.RandomWallet(integration.TenChainID), datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + _, err = user0.HTTPClient.ChainID(context.Background()) + require.NoError(t, err) + + user1, err := NewGatewayUser([]wallet.Wallet{datagenerator.RandomWallet(integration.TenChainID), datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) require.NoError(t, err) testlog.Logger().Info("Created user with encryption token", "t", user1.tgClient.UserID()) - user2, err := NewUser([]wallet.Wallet{datagenerator.RandomWallet(integration.TenChainID), datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + user2, err := NewGatewayUser([]wallet.Wallet{datagenerator.RandomWallet(integration.TenChainID), datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) require.NoError(t, err) testlog.Logger().Info("Created user with encryption token", "t", user2.tgClient.UserID()) @@ -154,12 +159,7 @@ func testMultipleAccountsSubscription(t *testing.T, httpURL, wsURL string, w wal require.NoError(t, err) // Print balances of all registered accounts to check if all accounts have funds - balances, err := user0.GetUserAccountsBalances() - require.NoError(t, err) - for _, balance := range balances { - require.NotZero(t, balance.Uint64()) - } - balances, err = user1.GetUserAccountsBalances() + balances, err := user1.GetUserAccountsBalances() require.NoError(t, err) for _, balance := range balances { require.NotZero(t, balance.Uint64()) @@ -190,6 +190,9 @@ func testMultipleAccountsSubscription(t *testing.T, httpURL, wsURL string, w wal contractReceipt, err := integrationCommon.AwaitReceiptEth(context.Background(), user0.HTTPClient, signedTx.Hash(), time.Minute) require.NoError(t, err) + _, err = user0.HTTPClient.CodeAt(context.Background(), contractReceipt.ContractAddress, big.NewInt(int64(rpc.LatestBlockNumber))) + require.NoError(t, err) + // check if value was changed in the smart contract with the interactions above pack, _ := eventsContractABI.Pack("message2") result, err := user1.HTTPClient.CallContract(context.Background(), ethereum.CallMsg{ @@ -210,9 +213,12 @@ func testMultipleAccountsSubscription(t *testing.T, httpURL, wsURL string, w wal var user0logs []types.Log var user1logs []types.Log var user2logs []types.Log - subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user0.WSClient, &user0logs) - subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user1.WSClient, &user1logs) - subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user2.WSClient, &user2logs) + _, err = subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user0.WSClient, &user0logs) + require.NoError(t, err) + _, err = subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user1.WSClient, &user1logs) + require.NoError(t, err) + _, err = subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user2.WSClient, &user2logs) + require.NoError(t, err) // user1 calls setMessage and setMessage2 on deployed smart contract with the account // that was registered as the first in TG @@ -265,13 +271,21 @@ func testMultipleAccountsSubscription(t *testing.T, httpURL, wsURL string, w wal assert.Equal(t, 3, len(user1logs)) // user2 should see three events (two lifecycle events - same as user0) and event with his interaction with setMessage assert.Equal(t, 3, len(user2logs)) + + _, err = user0.HTTPClient.FilterLogs(context.TODO(), ethereum.FilterQuery{ + Addresses: []gethcommon.Address{contractReceipt.ContractAddress}, + FromBlock: big.NewInt(0), + ToBlock: big.NewInt(10000), + Topics: nil, + }) + require.NoError(t, err) } func testSubscriptionTopics(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { - user0, err := NewUser([]wallet.Wallet{w}, httpURL, wsURL) + user0, err := NewGatewayUser([]wallet.Wallet{w}, httpURL, wsURL) require.NoError(t, err) - user1, err := NewUser([]wallet.Wallet{datagenerator.RandomWallet(integration.TenChainID), datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + user1, err := NewGatewayUser([]wallet.Wallet{datagenerator.RandomWallet(integration.TenChainID), datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) require.NoError(t, err) // register all the accounts for that user @@ -319,6 +333,12 @@ func testSubscriptionTopics(t *testing.T, httpURL, wsURL string, w wallet.Wallet contractReceipt, err := integrationCommon.AwaitReceiptEth(context.Background(), user0.HTTPClient, signedTx.Hash(), time.Minute) require.NoError(t, err) + tx, _, err := user0.HTTPClient.TransactionByHash(context.Background(), signedTx.Hash()) + if err != nil { + return + } + require.Equal(t, signedTx.Hash(), tx.Hash()) + // user0 subscribes to all events from that smart contract, user1 only an event with a topic of his first account var user0logs []types.Log var user1logs []types.Log @@ -326,8 +346,10 @@ func testSubscriptionTopics(t *testing.T, httpURL, wsURL string, w wallet.Wallet t1 := gethcommon.BytesToHash(user1.Wallets[1].Address().Bytes()) topics = append(topics, nil) topics = append(topics, []gethcommon.Hash{t1}) - subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user0.WSClient, &user0logs) - subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, topics, user1.WSClient, &user1logs) + _, err = subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user0.WSClient, &user0logs) + require.NoError(t, err) + _, err = subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, topics, user1.WSClient, &user1logs) + require.NoError(t, err) // user0 calls setMessage on deployed smart contract with the account twice and expects two events _, err = integrationCommon.InteractWithSmartContract(user0.HTTPClient, user0.Wallets[0], eventsContractABI, "setMessage", "user0Event1", contractReceipt.ContractAddress) @@ -394,28 +416,41 @@ func testErrorHandling(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { // make requests to geth for comparison for _, req := range []string{ + `{"jsonrpc":"2.0","method":"eth_getLogs","params":[[]],"id":1}`, + `{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":[]}],"id":1}`, + `{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x387","topics":["0xc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b"]}],"id":1}`, + //`{"jsonrpc":"2.0","method":"eth_subscribe","params":["logs"],"id":1}`, + //`{"jsonrpc":"2.0","method":"eth_subscribe","params":["logs",{"topics":[]}],"id":1}`, + `{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}`, + `{"jsonrpc":"2.0","method":"eth_blockNumber","params": [],"id":1}`, // test caching + `{"jsonrpc":"2.0","method":"eth_gasPrice","params": [],"id":1}`, + `{"jsonrpc":"2.0","method":"eth_gasPrice","params": [],"id":1}`, // test caching + `{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params": ["latest", false],"id":1}`, + `{"jsonrpc":"2.0","method":"eth_feeHistory","params":[1, "latest", [50]],"id":1}`, `{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xA58C60cc047592DE97BF1E8d2f225Fc5D959De77", "latest"],"id":1}`, `{"jsonrpc":"2.0","method":"eth_getBalance","params":[],"id":1}`, - `{"jsonrpc":"2.0","method":"eth_getgetget","params":["0xA58C60cc047592DE97BF1E8d2f225Fc5D959De77", "latest"],"id":1}`, + //`{"jsonrpc":"2.0","method":"eth_getgetget","params":["0xA58C60cc047592DE97BF1E8d2f225Fc5D959De77", "latest"],"id":1}`, `{"method":"eth_getBalance","params":["0xA58C60cc047592DE97BF1E8d2f225Fc5D959De77", "latest"],"id":1}`, `{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xA58C60cc047592DE97BF1E8d2f225Fc5D959De77", "latest"],"id":1,"extra":"extra_field"}`, `{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[["0xA58C60cc047592DE97BF1E8d2f225Fc5D959De77", "0x1234"]],"id":1}`, + `{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x0000000000000000000000000000000000000000000000000000000000000000"],"id":1}`, } { // ensure the geth request is issued correctly (should return 200 ok with jsonRPCError) _, response, err := httputil.PostDataJSON(ogClient.HTTP(), []byte(req)) require.NoError(t, err) + fmt.Printf("Resp: %s", response) // unmarshall the response to JSONRPCMessage - jsonRPCError := wecommon.JSONRPCMessage{} + jsonRPCError := JSONRPCMessage{} err = json.Unmarshal(response, &jsonRPCError) - require.NoError(t, err) + require.NoError(t, err, req, response) // repeat the process for the gateway _, response, err = httputil.PostDataJSON(fmt.Sprintf("http://localhost:%d", integration.StartPortTenGatewayUnitTest), []byte(req)) require.NoError(t, err) // we only care about format - jsonRPCError = wecommon.JSONRPCMessage{} + jsonRPCError = JSONRPCMessage{} err = json.Unmarshal(response, &jsonRPCError) require.NoError(t, err) } @@ -473,7 +508,7 @@ func testErrorsRevertedArePassed(t *testing.T, httpURL, wsURL string, w wallet.W // convert error to WE error errBytes, err := json.Marshal(err) require.NoError(t, err) - weError := wecommon.JSONError{} + weError := JSONError{} err = json.Unmarshal(errBytes, &weError) require.NoError(t, err) require.Equal(t, "execution reverted: Forced require", weError.Message) @@ -502,9 +537,12 @@ func testErrorsRevertedArePassed(t *testing.T, httpURL, wsURL string, w wallet.W func testUnsubscribe(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { // create a user with multiple accounts - user, err := NewUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + user, err := NewGatewayUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + require.NoError(t, err) + testlog.Logger().Info("Created user with encryption token", "t", user.tgClient.UserID()) + + _, err = user.HTTPClient.ChainID(context.Background()) require.NoError(t, err) - testlog.Logger().Info("Created user with encryption token: %s\n", user.tgClient.UserID()) // register all the accounts for the user err = user.RegisterAccounts() @@ -529,11 +567,12 @@ func testUnsubscribe(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { contractReceipt, err := integrationCommon.AwaitReceiptEth(context.Background(), user.HTTPClient, signedTx.Hash(), time.Minute) require.NoError(t, err) - testlog.Logger().Info("Deployed contract address: ", contractReceipt.ContractAddress) + testlog.Logger().Info("Deployed contract address: ", "addr", contractReceipt.ContractAddress) // subscribe to an event var userLogs []types.Log - subscription := subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user.WSClient, &userLogs) + subscription, err := subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user.WSClient, &userLogs) + require.NoError(t, err) // make an action that will trigger events _, err = integrationCommon.InteractWithSmartContract(user.HTTPClient, user.Wallets[0], eventsContractABI, "setMessage", "foo", contractReceipt.ContractAddress) @@ -554,9 +593,12 @@ func testUnsubscribe(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { func testClosingConnectionWhileSubscribed(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { // create a user with multiple accounts - user, err := NewUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + user, err := NewGatewayUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + require.NoError(t, err) + testlog.Logger().Info("Created user with encryption token", "t", user.tgClient.UserID()) + + _, err = user.HTTPClient.ChainID(context.Background()) require.NoError(t, err) - testlog.Logger().Info("Created user with encryption token: %s\n", user.tgClient.UserID()) // register all the accounts for the user err = user.RegisterAccounts() @@ -581,11 +623,12 @@ func testClosingConnectionWhileSubscribed(t *testing.T, httpURL, wsURL string, w contractReceipt, err := integrationCommon.AwaitReceiptEth(context.Background(), user.HTTPClient, signedTx.Hash(), time.Minute) require.NoError(t, err) - testlog.Logger().Info("Deployed contract address: ", contractReceipt.ContractAddress) + testlog.Logger().Info("Deployed contract address: ", "addr", contractReceipt.ContractAddress) // subscribe to an event var userLogs []types.Log - subscription := subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user.WSClient, &userLogs) + subscription, err := subscribeToEvents([]gethcommon.Address{contractReceipt.ContractAddress}, nil, user.WSClient, &userLogs) + require.NoError(t, err) // Close the websocket connection and make sure nothing breaks, but user does not receive events user.WSClient.Close() @@ -613,7 +656,7 @@ func testClosingConnectionWhileSubscribed(t *testing.T, httpURL, wsURL string, w } func testDifferentMessagesOnRegister(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { - user, err := NewUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + user, err := NewGatewayUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) require.NoError(t, err) testlog.Logger().Info("Created user with encryption token: %s\n", user.tgClient.UserID()) @@ -627,19 +670,19 @@ func testDifferentMessagesOnRegister(t *testing.T, httpURL, wsURL string, w wall } func testInvokeNonSensitiveMethod(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { - user, err := NewUser([]wallet.Wallet{w}, httpURL, wsURL) + user, err := NewGatewayUser([]wallet.Wallet{w}, httpURL, wsURL) require.NoError(t, err) // call one of the non-sensitive methods with unauthenticated user // and make sure gateway is not complaining about not having viewing keys - respBody := makeHTTPEthJSONReq(httpURL, rpc.ChainID, user.tgClient.UserID(), nil) - if strings.Contains(string(respBody), fmt.Sprintf("method %s cannot be called with an unauthorised client - no signed viewing keys found", rpc.ChainID)) { - t.Errorf("sensitive method called without authenticating viewingkeys and did fail because of it: %s", rpc.ChainID) + respBody := makeHTTPEthJSONReq(httpURL, tenrpc.ChainID, user.tgClient.UserID(), nil) + if strings.Contains(string(respBody), fmt.Sprintf("method %s cannot be called with an unauthorised client - no signed viewing keys found", tenrpc.ChainID)) { + t.Errorf("sensitive method called without authenticating viewingkeys and did fail because of it: %s", tenrpc.ChainID) } } func testGetStorageAtForReturningUserID(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { - user, err := NewUser([]wallet.Wallet{w}, httpURL, wsURL) + user, err := NewGatewayUser([]wallet.Wallet{w}, httpURL, wsURL) require.NoError(t, err) type JSONResponse struct { @@ -648,24 +691,24 @@ func testGetStorageAtForReturningUserID(t *testing.T, httpURL, wsURL string, w w var response JSONResponse // make a request to GetStorageAt with correct parameters to get userID that exists in the database - respBody := makeHTTPEthJSONReq(httpURL, rpc.GetStorageAt, user.tgClient.UserID(), []interface{}{"getUserID", "0", nil}) + respBody := makeHTTPEthJSONReq(httpURL, tenrpc.GetStorageAt, user.tgClient.UserID(), []interface{}{wecommon.GetStorageAtUserIDRequestMethodName, "0", nil}) if err = json.Unmarshal(respBody, &response); err != nil { t.Error("Unable to unmarshal response") } - if response.Result != user.tgClient.UserID() { + if !bytes.Equal(gethcommon.FromHex(response.Result), user.tgClient.UserIDBytes()) { t.Errorf("Wrong UserID returned. Expected: %s, received: %s", user.tgClient.UserID(), response.Result) } // make a request to GetStorageAt with correct parameters to get userID, but with wrong userID - respBody2 := makeHTTPEthJSONReq(httpURL, rpc.GetStorageAt, "invalid_user_id", []interface{}{"getUserID", "0", nil}) - if !strings.Contains(string(respBody2), "method eth_getStorageAt cannot be called with an unauthorised client - no signed viewing keys found") { - t.Error("eth_getStorageAt did not respond with error: method eth_getStorageAt cannot be called with an unauthorised client - no signed viewing keys found") + respBody2 := makeHTTPEthJSONReq(httpURL, tenrpc.GetStorageAt, "0x0000000000000000000000000000000000000001", []interface{}{wecommon.GetStorageAtUserIDRequestMethodName, "0", nil}) + if !strings.Contains(string(respBody2), "not found") { + t.Error("eth_getStorageAt did not respond with not found error") } // make a request to GetStorageAt with wrong parameters to get userID, but correct userID - respBody3 := makeHTTPEthJSONReq(httpURL, rpc.GetStorageAt, user.tgClient.UserID(), []interface{}{"abc", "0", nil}) - if !strings.Contains(string(respBody3), "method eth_getStorageAt cannot be called with an unauthorised client - no signed viewing keys found") { - t.Error("eth_getStorageAt did not respond with error: no signed viewing keys found") + respBody3 := makeHTTPEthJSONReq(httpURL, tenrpc.GetStorageAt, user.tgClient.UserID(), []interface{}{"0x0000000000000000000000000000000000000001", "0", nil}) + if !strings.Contains(string(respBody3), "illegal access") { + t.Error("eth_getStorageAt did not respond with error: illegal access") } } @@ -759,7 +802,7 @@ func createTenNetwork(t *testing.T, startPort int) { func waitServerIsReady(serverAddr string) error { for now := time.Now(); time.Since(now) < 30*time.Second; time.Sleep(500 * time.Millisecond) { - statusCode, _, err := fasthttp.Get(nil, fmt.Sprintf("%s/health/", serverAddr)) + statusCode, _, err := fasthttp.Get(nil, fmt.Sprintf("%s/v1/health/", serverAddr)) if err != nil { // give it time to boot up if strings.Contains(err.Error(), "connection") { @@ -778,13 +821,13 @@ func waitServerIsReady(serverAddr string) error { func getFeeAndGas(client *ethclient.Client, wallet wallet.Wallet, legacyTx *types.LegacyTx) error { tx := types.NewTx(legacyTx) - history, err := client.FeeHistory(context.Background(), 1, nil, []float64{}) + history, err := client.FeeHistory(context.Background(), 1, nil, nil) if err != nil || len(history.BaseFee) == 0 { return err } estimate, err := client.EstimateGas(context.Background(), ethereum.CallMsg{ - From: wallet.Address(), + // From: wallet.Address(), To: tx.To(), Value: tx.Value(), Data: tx.Data(), @@ -825,19 +868,20 @@ func transferETHToAddress(client *ethclient.Client, wallet wallet.Wallet, toAddr return integrationCommon.AwaitReceiptEth(context.Background(), client, signedTx.Hash(), 30*time.Second) } -func subscribeToEvents(addresses []gethcommon.Address, topics [][]gethcommon.Hash, client *ethclient.Client, logs *[]types.Log) ethereum.Subscription { +func subscribeToEvents(addresses []gethcommon.Address, topics [][]gethcommon.Hash, client *ethclient.Client, logs *[]types.Log) (ethereum.Subscription, error) { // Make a subscription filterQuery := ethereum.FilterQuery{ Addresses: addresses, - FromBlock: big.NewInt(0), // todo (@ziga) - without those we get errors - fix that and make them configurable - ToBlock: big.NewInt(10000), - Topics: topics, + FromBlock: big.NewInt(2), + // ToBlock: big.NewInt(10000), + Topics: topics, } logsCh := make(chan types.Log) subscription, err := client.SubscribeFilterLogs(context.Background(), filterQuery, logsCh) if err != nil { - testlog.Logger().Info("Failed to subscribe to filter logs: %v", log2.ErrKey, err) + testlog.Logger().Info("Failed to subscribe to filter logs", log2.ErrKey, err) + return nil, err } // Listen for logs in a goroutine @@ -845,7 +889,7 @@ func subscribeToEvents(addresses []gethcommon.Address, topics [][]gethcommon.Has for { select { case err := <-subscription.Err(): - testlog.Logger().Info("Error from logs subscription: %v", log2.ErrKey, err) + testlog.Logger().Info("Error from logs subscription", log2.ErrKey, err) return case log := <-logsCh: // append logs to be visible from the main thread @@ -854,5 +898,5 @@ func subscribeToEvents(addresses []gethcommon.Address, topics [][]gethcommon.Has } }() - return subscription + return subscription, nil } diff --git a/integration/simulation/devnetwork/dev_network.go b/integration/simulation/devnetwork/dev_network.go index 3ac1be6060..25cd70f86b 100644 --- a/integration/simulation/devnetwork/dev_network.go +++ b/integration/simulation/devnetwork/dev_network.go @@ -7,10 +7,11 @@ import ( "sync" "time" + "github.com/ten-protocol/go-ten/tools/walletextension" + wecommon "github.com/ten-protocol/go-ten/tools/walletextension/common" + "github.com/ten-protocol/go-ten/integration/common/testlog" "github.com/ten-protocol/go-ten/integration/simulation/network" - gatewaycfg "github.com/ten-protocol/go-ten/tools/walletextension/config" - "github.com/ten-protocol/go-ten/tools/walletextension/container" "github.com/ten-protocol/go-ten/go/ethadapter" @@ -57,7 +58,7 @@ type InMemDevNetwork struct { tenConfig *TenConfig tenSequencer *InMemNodeOperator tenValidators []*InMemNodeOperator - tenGatewayContainer *container.WalletExtensionContainer + tenGatewayContainer *walletextension.Container faucet userwallet.User faucetLock sync.Mutex @@ -192,7 +193,7 @@ func (s *InMemDevNetwork) startTenGateway() { validatorWS := validator.HostRPCWSAddress() // remove ws:// prefix for the gateway config validatorWS = validatorWS[len("ws://"):] - cfg := gatewaycfg.Config{ + cfg := wecommon.Config{ WalletExtensionHost: "127.0.0.1", WalletExtensionPortHTTP: _gwHTTPPort, WalletExtensionPortWS: _gwWSPort, @@ -203,7 +204,7 @@ func (s *InMemDevNetwork) startTenGateway() { DBType: "sqlite", TenChainID: integration.TenChainID, } - tenGWContainer := container.NewWalletExtensionContainerFromConfig(cfg, s.logger) + tenGWContainer := walletextension.NewContainerFromConfig(cfg, s.logger) go func() { fmt.Println("Starting Ten Gateway, HTTP Port:", _gwHTTPPort, "WS Port:", _gwWSPort) err := tenGWContainer.Start() diff --git a/integration/simulation/simulation.go b/integration/simulation/simulation.go index d2ab17b953..68dc37e895 100644 --- a/integration/simulation/simulation.go +++ b/integration/simulation/simulation.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/filters" gethparams "github.com/ethereum/go-ethereum/params" "github.com/ten-protocol/go-ten/contracts/generated/MessageBus" "github.com/ten-protocol/go-ten/go/common" @@ -192,7 +191,7 @@ func (s *Simulation) trackLogs() { channel := make(chan common.IDAndLog, 1000) // To exercise the filtering mechanism, we subscribe for HOC events only, ignoring POC events. - hocFilter := filters.FilterCriteria{ + hocFilter := common.FilterCriteria{ Addresses: []gethcommon.Address{gethcommon.HexToAddress("0x" + testcommon.HOCAddr)}, } sub, err := client.SubscribeFilterLogs(context.Background(), hocFilter, channel) diff --git a/integration/simulation/validate_chain.go b/integration/simulation/validate_chain.go index c7010f1747..5fa4809065 100644 --- a/integration/simulation/validate_chain.go +++ b/integration/simulation/validate_chain.go @@ -627,7 +627,7 @@ func checkSubscribedLogs(t *testing.T, owner string, channel chan common.IDAndLo func checkSnapshotLogs(t *testing.T, client *obsclient.AuthObsClient) int { // To exercise the filtering mechanism, we get a snapshot for HOC events only, ignoring POC events. - hocFilter := common.FilterCriteriaJSON{ + hocFilter := common.FilterCriteria{ Addresses: []gethcommon.Address{gethcommon.HexToAddress("0x" + testcommon.HOCAddr)}, } logs, err := client.GetLogs(context.Background(), hocFilter) diff --git a/lib/gethfork/rpc/client.go b/lib/gethfork/rpc/client.go index de7fd5396a..805f375441 100644 --- a/lib/gethfork/rpc/client.go +++ b/lib/gethfork/rpc/client.go @@ -76,7 +76,7 @@ type BatchElem struct { // Client represents a connection to an RPC server. type Client struct { - UserID string + UserID []byte idgen func() ID // for subscriptions isHTTP bool // connection type: http, ws or ipc services *serviceRegistry diff --git a/lib/gethfork/rpc/client_opt.go b/lib/gethfork/rpc/client_opt.go index 0eae2e6134..32435e8efb 100644 --- a/lib/gethfork/rpc/client_opt.go +++ b/lib/gethfork/rpc/client_opt.go @@ -28,7 +28,7 @@ type ClientOption interface { } type clientConfig struct { - UserID string + UserID []byte // HTTP settings httpClient *http.Client httpHeaders http.Header diff --git a/lib/gethfork/rpc/handler.go b/lib/gethfork/rpc/handler.go index 856ef8b2c4..8836f3c6b5 100644 --- a/lib/gethfork/rpc/handler.go +++ b/lib/gethfork/rpc/handler.go @@ -25,6 +25,8 @@ import ( "sync" "time" + "github.com/status-im/keycard-go/hexutils" + "github.com/ethereum/go-ethereum/log" ) @@ -65,7 +67,7 @@ type handler struct { subLock sync.Mutex serverSubs map[ID]*Subscription - UserID string + UserID []byte } type callProc struct { @@ -73,7 +75,7 @@ type callProc struct { notifiers []*Notifier } -func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *serviceRegistry, batchRequestLimit, batchResponseMaxSize int, userID string) *handler { +func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *serviceRegistry, batchRequestLimit, batchResponseMaxSize int, userID []byte) *handler { rootCtx, cancelRoot := context.WithCancel(connCtx) h := &handler{ reg: reg, @@ -386,6 +388,10 @@ func (h *handler) startCallProc(fn func(*callProc)) { ctx, cancel := context.WithCancel(h.rootCtx) defer h.callWG.Done() defer cancel() + // handle the case when normal rpc calls are made over a ws connection + if ctx.Value(GWTokenKey{}) == nil { + ctx = context.WithValue(ctx, GWTokenKey{}, hexutils.BytesToHex(h.UserID)) + } fn(&callProc{ctx: ctx}) }() } diff --git a/lib/gethfork/rpc/inproc.go b/lib/gethfork/rpc/inproc.go index 2a5d400b19..835825334b 100644 --- a/lib/gethfork/rpc/inproc.go +++ b/lib/gethfork/rpc/inproc.go @@ -27,7 +27,7 @@ func DialInProc(handler *Server) *Client { cfg := new(clientConfig) c, _ := newClient(initctx, cfg, func(context.Context) (ServerCodec, error) { p1, p2 := net.Pipe() - go handler.ServeCodec(NewCodec(p1), 0, "") + go handler.ServeCodec(NewCodec(p1), 0, nil) return NewCodec(p2), nil }) return c diff --git a/lib/gethfork/rpc/ipc.go b/lib/gethfork/rpc/ipc.go index 9db95dc467..5f45a4cb07 100644 --- a/lib/gethfork/rpc/ipc.go +++ b/lib/gethfork/rpc/ipc.go @@ -35,7 +35,7 @@ func (s *Server) ServeListener(l net.Listener) error { return err } log.Trace("Accepted RPC connection", "conn", conn.RemoteAddr()) - go s.ServeCodec(NewCodec(conn), 0, "") + go s.ServeCodec(NewCodec(conn), 0, nil) } } diff --git a/lib/gethfork/rpc/server.go b/lib/gethfork/rpc/server.go index e0b96ad53f..686afe5a02 100644 --- a/lib/gethfork/rpc/server.go +++ b/lib/gethfork/rpc/server.go @@ -18,7 +18,6 @@ package rpc import ( "context" - "fmt" "io" "sync" "sync/atomic" @@ -103,7 +102,7 @@ func (s *Server) RegisterName(name string, receiver interface{}) error { // server is stopped. In either case the codec is closed. // // Note that codec options are no longer supported. -func (s *Server) ServeCodec(codec ServerCodec, _ CodecOption, userID string) { +func (s *Server) ServeCodec(codec ServerCodec, _ CodecOption, userID []byte) { defer codec.close() if !s.trackCodec(codec) { @@ -149,7 +148,7 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { return } - h := newHandler(ctx, codec, s.idgen, &s.services, s.batchItemLimit, s.batchResponseLimit, "") + h := newHandler(ctx, codec, s.idgen, &s.services, s.batchItemLimit, s.batchResponseLimit, nil) h.allowSubscribe = false defer h.close(io.EOF, nil) @@ -157,7 +156,6 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { if err != nil { if err != io.EOF { resp := errorMessage(&invalidMessageError{"parse error"}) - fmt.Printf(">> Parse error %s. requests: %v\n", err, reqs) codec.writeJSON(ctx, resp, true) } return diff --git a/lib/gethfork/rpc/subscription.go b/lib/gethfork/rpc/subscription.go index c7fbc6c8c2..ca432190fb 100644 --- a/lib/gethfork/rpc/subscription.go +++ b/lib/gethfork/rpc/subscription.go @@ -101,7 +101,7 @@ func NotifierFromContext(ctx context.Context) (*Notifier, bool) { // Server callbacks use the notifier to send notifications. type Notifier struct { h *handler - UserID string // added by TEN + UserID []byte // added by TEN namespace string mu sync.Mutex diff --git a/lib/gethfork/rpc/websocket.go b/lib/gethfork/rpc/websocket.go index 605931c47d..9db7e19e40 100644 --- a/lib/gethfork/rpc/websocket.go +++ b/lib/gethfork/rpc/websocket.go @@ -27,6 +27,10 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/common" + + "github.com/ten-protocol/go-ten/go/common/viewingkey" + mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/log" "github.com/gorilla/websocket" @@ -65,12 +69,16 @@ func (s *Server) WebsocketHandler(allowedOrigins []string) http.Handler { }) } -func extractUserID(ctx context.Context) string { +func extractUserID(ctx context.Context) []byte { token, ok := ctx.Value(GWTokenKey{}).(string) if !ok { - return "" + return nil + } + userID := common.FromHex(token) + if len(userID) != viewingkey.UserIDLength { + return nil } - return token + return userID } // wsHandshakeValidator returns a handler that verifies the origin during the diff --git a/testnet/launcher/eth2network/docker.go b/testnet/launcher/eth2network/docker.go index 65685833f5..144e13dbf4 100644 --- a/testnet/launcher/eth2network/docker.go +++ b/testnet/launcher/eth2network/docker.go @@ -50,7 +50,7 @@ func (n *Eth2Network) Start() error { } func (n *Eth2Network) IsReady() error { - timeout := 10 * time.Minute + timeout := 20 * time.Minute // this can be reduced when we no longer download the ethereum binaries interval := 2 * time.Second var dial *ethclient.Client var err error diff --git a/testnet/launcher/gateway/docker.go b/testnet/launcher/gateway/docker.go index 1827516cf9..3bde82b592 100644 --- a/testnet/launcher/gateway/docker.go +++ b/testnet/launcher/gateway/docker.go @@ -43,7 +43,7 @@ func (n *DockerGateway) IsReady() error { interval := time.Second return retry.Do(func() error { - statusCode, _, err := fasthttp.Get(nil, fmt.Sprintf("http://127.0.0.1:%d/health/", n.cfg.gatewayHTTPPort)) + statusCode, _, err := fasthttp.Get(nil, fmt.Sprintf("http://127.0.0.1:%d/v1/health/", n.cfg.gatewayHTTPPort)) if err != nil { return err } diff --git a/tools/tenscan/frontend/pages/_app.tsx b/tools/tenscan/frontend/pages/_app.tsx index 287ecf806d..e8c8d12077 100644 --- a/tools/tenscan/frontend/pages/_app.tsx +++ b/tools/tenscan/frontend/pages/_app.tsx @@ -69,7 +69,7 @@ export default function App({ Component, pageProps }: AppProps) { ogTwitterImage={siteMetadata.siteLogo} ogType={"website"} > - + diff --git a/tools/tenscan/frontend/src/components/layouts/header.tsx b/tools/tenscan/frontend/src/components/layouts/header.tsx index a04de0fea8..3a2e59b40a 100644 --- a/tools/tenscan/frontend/src/components/layouts/header.tsx +++ b/tools/tenscan/frontend/src/components/layouts/header.tsx @@ -14,7 +14,7 @@ export default function Header() {