From 6ac6e27d012583ad98d9cba5103318cd8f7d339d Mon Sep 17 00:00:00 2001 From: Chase Ripplinger Date: Tue, 11 May 2021 12:59:32 -0500 Subject: [PATCH] Implement most of eth_subscribe in a websocket --- pkg/eth/eth_address.go | 60 +++ pkg/eth/rpc_types.go | 60 +++ pkg/eth/rpc_types_test.go | 47 +++ pkg/eth/util.go | 35 ++ pkg/notifier/agent.go | 350 ++++++++++++++++++ pkg/notifier/notifier.go | 169 +++++++++ pkg/qtum/client.go | 21 +- pkg/qtum/method.go | 18 + pkg/qtum/rpc_types.go | 36 ++ pkg/server/handler.go | 244 +++++++++++- pkg/server/myctx.go | 38 +- pkg/server/server.go | 6 +- pkg/transformer/eth_accounts.go | 3 +- pkg/transformer/eth_accounts_test.go | 2 +- pkg/transformer/eth_blockNumber.go | 3 +- pkg/transformer/eth_blockNumber_test.go | 2 +- pkg/transformer/eth_call.go | 3 +- pkg/transformer/eth_call_test.go | 4 +- pkg/transformer/eth_chainId.go | 3 +- pkg/transformer/eth_estimateGas.go | 3 +- pkg/transformer/eth_estimateGas_test.go | 2 +- pkg/transformer/eth_gasPrice.go | 3 +- pkg/transformer/eth_gasPrice_test.go | 2 +- pkg/transformer/eth_getBalance.go | 3 +- pkg/transformer/eth_getBalance_test.go | 4 +- pkg/transformer/eth_getBlockByHash.go | 3 +- pkg/transformer/eth_getBlockByNumber.go | 3 +- pkg/transformer/eth_getBlockByNumber_test.go | 2 +- pkg/transformer/eth_getCode.go | 3 +- pkg/transformer/eth_getCode_test.go | 4 +- pkg/transformer/eth_getCompilers.go | 3 +- pkg/transformer/eth_getCompilers_test.go | 2 +- pkg/transformer/eth_getFilterChanges.go | 3 +- pkg/transformer/eth_getFilterChanges_test.go | 6 +- pkg/transformer/eth_getFilterLogs.go | 6 +- pkg/transformer/eth_getLogs.go | 5 +- pkg/transformer/eth_getLogs_test.go | 4 +- pkg/transformer/eth_getStorageAt.go | 3 +- pkg/transformer/eth_getStorageAt_test.go | 6 +- .../eth_getTransactionByBlockHashAndIndex.go | 3 +- ...eth_getTransactionByBlockNumberAndIndex.go | 3 +- pkg/transformer/eth_getTransactionByHash.go | 3 +- .../eth_getTransactionByHash_test.go | 2 +- pkg/transformer/eth_getTransactionCount.go | 3 +- .../eth_getTransactionCount_test.go | 2 +- pkg/transformer/eth_getTransactionReceipt.go | 3 +- .../eth_getUncleByBlockHashAndIndex.go | 3 +- .../eth_getUncleByBlockHashAndIndex_test.go | 2 +- pkg/transformer/eth_hashrate.go | 3 +- pkg/transformer/eth_hashrate_test.go | 2 +- pkg/transformer/eth_mining.go | 3 +- pkg/transformer/eth_mining_test.go | 2 +- pkg/transformer/eth_net_listening.go | 3 +- pkg/transformer/eth_net_listening_test.go | 2 +- pkg/transformer/eth_net_peerCount.go | 3 +- pkg/transformer/eth_net_peerCount_test.go | 2 +- pkg/transformer/eth_net_version.go | 3 +- pkg/transformer/eth_newBlockFilter.go | 3 +- pkg/transformer/eth_newFilter.go | 5 +- pkg/transformer/eth_personal_unlockAccount.go | 3 +- pkg/transformer/eth_protocolVersion.go | 3 +- pkg/transformer/eth_protocolVersion_test.go | 2 +- pkg/transformer/eth_sendRawTransaction.go | 3 +- pkg/transformer/eth_sendTransaction.go | 3 +- pkg/transformer/eth_sign.go | 3 +- pkg/transformer/eth_signTransaction.go | 3 +- pkg/transformer/eth_subscribe.go | 52 +++ pkg/transformer/eth_uninstallFilter.go | 3 +- pkg/transformer/notifier.go | 15 + pkg/transformer/qtum_getUTXOs.go | 3 +- pkg/transformer/tests_common.go | 2 +- pkg/transformer/transformer.go | 13 +- pkg/transformer/type.go | 3 +- pkg/transformer/util.go | 29 -- pkg/transformer/web3_clientVersion.go | 3 +- pkg/transformer/web3_sha3.go | 3 +- pkg/transformer/web3_sha3_test.go | 4 +- 77 files changed, 1259 insertions(+), 120 deletions(-) create mode 100644 pkg/eth/eth_address.go create mode 100644 pkg/eth/rpc_types_test.go create mode 100644 pkg/eth/util.go create mode 100644 pkg/notifier/agent.go create mode 100644 pkg/notifier/notifier.go create mode 100644 pkg/transformer/eth_subscribe.go create mode 100644 pkg/transformer/notifier.go diff --git a/pkg/eth/eth_address.go b/pkg/eth/eth_address.go new file mode 100644 index 00000000..26de127e --- /dev/null +++ b/pkg/eth/eth_address.go @@ -0,0 +1,60 @@ +package eth + +import ( + "encoding/json" + "strings" + + "github.com/pkg/errors" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var ErrNoHexPrefix = errors.New("Missing 0x prefix") +var ErrInvalidLength = errors.New("Invalid length") + +type ETHAddress struct { + address string +} + +func (addr *ETHAddress) String() string { + return addr.address +} + +func (addr ETHAddress) MarshalJSON() ([]byte, error) { + if err := validateAddress(addr.address); err != nil { + return []byte{}, err + } + + return json.Marshal(addr.address) +} + +// UnmarshalJSON needs to be able to parse ETHAddress from both hex string or number +func (addr *ETHAddress) UnmarshalJSON(data []byte) (err error) { + asString := string(data) + if strings.HasPrefix(asString, `"`) && strings.HasSuffix(asString, `"`) { + asString = asString[1 : len(asString)-1] + } + if err := validateAddress(asString); err != nil { + return err + } + + addr.address = asString + return nil +} + +func validateAddress(address string) error { + if !strings.HasPrefix(address, "0x") { + return ErrNoHexPrefix + } + + if len(address) != 42 { + return ErrInvalidLength + } + + _, err := hexutil.Decode(address) + if err != nil { + return errors.Wrap(err, "Invalid hexadecimal") + } + + return nil +} diff --git a/pkg/eth/rpc_types.go b/pkg/eth/rpc_types.go index 4d9e41bb..9bb4ab4c 100644 --- a/pkg/eth/rpc_types.go +++ b/pkg/eth/rpc_types.go @@ -635,6 +635,60 @@ func newErrInvalidParameterType(idx int, gotType interface{}, wantedType interfa return errors.Errorf("invalid %d parameter of %T type, but %T type is expected", idx, gotType, wantedType) } +// ========== eth_subscribe ============= // + +type ( + EthLogSubscriptionParameter struct { + Address ETHAddress `json:"address"` + Topics []interface{} `json:"topics"` + } + + EthSubscriptionRequest struct { + Method string + Params *EthLogSubscriptionParameter + } + + EthSubscriptionResponse string +) + +func (r *EthSubscriptionRequest) UnmarshalJSON(data []byte) error { + var params []interface{} + if err := json.Unmarshal(data, ¶ms); err != nil { + return errors.Wrap(err, "couldn't unmarhsal data") + } + + method, ok := params[0].(string) + if !ok { + return newErrInvalidParameterType(1, params[0], "") + } + r.Method = method + + if len(params) >= 2 { + param, err := json.Marshal(params[1]) + if err != nil { + return err + } + var subscriptionParameter EthLogSubscriptionParameter + err = json.Unmarshal(param, &subscriptionParameter) + if err != nil { + return err + } + r.Params = &subscriptionParameter + } + + return nil +} + +func (r EthSubscriptionRequest) MarshalJSON() ([]byte, error) { + output := []interface{}{} + output = append(output, r.Method) + if r.Params != nil { + output = append(output, r.Params) + } + + return json.Marshal(output) +} + // ========== eth_newFilter ============= // type NewFilterRequest struct { @@ -708,6 +762,12 @@ func (r *GetStorageRequest) UnmarshalJSON(data []byte) error { // ======= eth_chainId ============= // type ChainIdResponse string +// ======= eth_subscription ======== // +type EthSubscription struct { + SubscriptionID string `json:"subscription"` + Result interface{} `json:"result"` +} + // ======= qtum_getUTXOs ============= // type ( diff --git a/pkg/eth/rpc_types_test.go b/pkg/eth/rpc_types_test.go new file mode 100644 index 00000000..ce3861ad --- /dev/null +++ b/pkg/eth/rpc_types_test.go @@ -0,0 +1,47 @@ +package eth + +import ( + "encoding/json" + "testing" +) + +func TestEthLogSubscriptionRequestSerialization(t *testing.T) { + jsonValue := `["logs",{"address":"0x8320fe7702b96808f7bbc0d4a888ed1468216cfd","topics":["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]` + var request EthSubscriptionRequest + err := json.Unmarshal([]byte(jsonValue), &request) + if err != nil { + t.Fatal(err) + } + asJson, err := json.Marshal(request) + if err != nil { + t.Fatal(err) + } + if string(asJson) != jsonValue { + t.Fatalf(`"%s" != "%s"\n`, string(asJson), jsonValue) + } +} + +func TestEthLogSubscriptionRequestWithInvalidAddressSerialization(t *testing.T) { + jsonValue := `["logs",{"address":"0x0","topics":["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]` + var request EthSubscriptionRequest + err := json.Unmarshal([]byte(jsonValue), &request) + if err != ErrInvalidLength { + t.Fatal(err) + } +} + +func TestEthNewPendingTransactionsRequestSerialization(t *testing.T) { + jsonValue := `["newPendingTransactions"]` + var request EthSubscriptionRequest + err := json.Unmarshal([]byte(jsonValue), &request) + if err != nil { + t.Fatal(err) + } + asJson, err := json.Marshal(request) + if err != nil { + t.Fatal(err) + } + if string(asJson) != jsonValue { + t.Fatalf(`"%s" != "%s"\n`, string(asJson), jsonValue) + } +} diff --git a/pkg/eth/util.go b/pkg/eth/util.go new file mode 100644 index 00000000..2722784d --- /dev/null +++ b/pkg/eth/util.go @@ -0,0 +1,35 @@ +package eth + +import ( + "github.com/pkg/errors" + "github.com/qtumproject/janus/pkg/utils" +) + +// translateTopics takes in an ethReq's topics field and translates it to a it's equivalent QtumReq +// topics (optional) has a max lenght of 4 +func TranslateTopics(ethTopics []interface{}) ([]interface{}, error) { + + var topics []interface{} + + if len(ethTopics) > 4 { + return nil, errors.Errorf("invalid number of topics. Logs have a max of 4 topics.") + } + + for _, topic := range ethTopics { + switch topic.(type) { + case []interface{}: + topic, err := TranslateTopics(topic.([]interface{})) + if err != nil { + return nil, err + } + topics = append(topics, topic) + case string: + topics = append(topics, utils.RemoveHexPrefix(topic.(string))) + case nil: + topics = append(topics, nil) + } + } + + return topics, nil + +} diff --git a/pkg/notifier/agent.go b/pkg/notifier/agent.go new file mode 100644 index 00000000..b0dafda9 --- /dev/null +++ b/pkg/notifier/agent.go @@ -0,0 +1,350 @@ +package notifier + +import ( + "context" + "fmt" + "strings" + "sync" + "time" + + "github.com/pkg/errors" + "github.com/qtumproject/janus/pkg/eth" + "github.com/qtumproject/janus/pkg/qtum" +) + +func NewAgent(qtum *qtum.Qtum) *Agent { + agent := &Agent{ + qtum: qtum, + mutex: sync.RWMutex{}, + running: false, + stop: make(chan interface{}), + newHeads: newSubscriptionRegistry(), + logs: newSubscriptionRegistry(), + newPendingTxs: newSubscriptionRegistry(), + syncing: newSubscriptionRegistry(), + } + + go agent.run() + return agent +} + +type subscriptionRegistry struct { + mutex sync.RWMutex + subscriptionCount int + subscriptions map[string]*subscriptionInformation +} + +func newSubscriptionRegistry() *subscriptionRegistry { + return &subscriptionRegistry{ + mutex: sync.RWMutex{}, + subscriptionCount: 0, + subscriptions: make(map[string]*subscriptionInformation), + } +} + +type subscriptionInformation struct { + *Subscription + params *eth.EthSubscriptionRequest + mutex sync.RWMutex + ctx context.Context + cancelFunc context.CancelFunc + running bool + qtum *qtum.Qtum +} + +func (s *subscriptionInformation) run() { + if s.params == nil { + return + } + + if strings.ToLower(s.params.Method) != "logs" { + return + } + + s.mutex.Lock() + if s.running { + s.mutex.Unlock() + return + } + s.running = true + s.mutex.Unlock() + + defer func() { + s.mutex.Lock() + defer s.mutex.Unlock() + + s.running = false + }() + + nextBlock := 0 + qtumTopics, err := eth.TranslateTopics(s.params.Params.Topics) + if err != nil { + s.qtum.GetDebugLogger().Log("msg", "Error translating logs topics", "error", err) + return + } + req := &qtum.WaitForLogsRequest{ + FromBlock: nextBlock, + ToBlock: "latest", + Filter: qtum.WaitForLogsFilter{ + Topics: &qtumTopics, + }, + } + + failures := 0 + for { + s.qtum.GetDebugLogger().Log("msg", "calling waitforlogs") + req.FromBlock = nextBlock + resp, err := s.qtum.WaitForLogsWithContext(s.ctx, req) + if err == nil { + s.notifier.Send(ð.EthSubscription{ + SubscriptionID: s.Subscription.id, + Result: resp, + }) + failures = 0 + } else { + // error occurred + s.qtum.GetDebugLogger().Log("subscriptionId", s.id, "err", err) + failures = failures + 1 + } + + done := s.ctx.Done() + + select { + case <-done: + // err is wrapped so we can't detect (err == context.Cancelled) + s.qtum.GetDebugLogger().Log("subscriptionId", s.id, "msg", "context closed, dropping subscription") + return + default: + } + + backoffTime := getBackoff(failures, 0, 15*time.Second) + + if backoffTime > 0 { + s.qtum.GetDebugLogger().Log("subscriptionId", s.id, "msg", fmt.Sprintf("backing off for %d miliseconds", backoffTime/time.Millisecond)) + } + + select { + case <-done: + return + case <-time.After(backoffTime): + // ok, try again + } + } +} + +func getBackoff(count int, min time.Duration, max time.Duration) time.Duration { + maxFailures := 10 + if count == 0 { + return min + } + + if count > maxFailures { + return max + } + + return ((max - min) / time.Duration(maxFailures)) * time.Duration(count) +} + +type Agent struct { + qtum *qtum.Qtum + mutex sync.RWMutex + running bool + stop chan interface{} + newHeads *subscriptionRegistry + logs *subscriptionRegistry + newPendingTxs *subscriptionRegistry + syncing *subscriptionRegistry +} + +func (a *Agent) Stop() { + a.mutex.Lock() + a.lockAllRegistries(false) + defer a.unlockAllRegistries(false) + defer a.mutex.Unlock() + + closeSubscriptionRegistry(a.newHeads) + closeSubscriptionRegistry(a.logs) + closeSubscriptionRegistry(a.newPendingTxs) + closeSubscriptionRegistry(a.syncing) +} + +func closeSubscriptionRegistry(registry *subscriptionRegistry) { + for _, sub := range registry.subscriptions { + sub.cancelFunc() + } +} + +func (a *Agent) lockAllRegistries(readOnly bool) { + if readOnly { + a.newHeads.mutex.RLock() + a.logs.mutex.RLock() + a.newPendingTxs.mutex.RLock() + a.syncing.mutex.RLock() + } else { + a.newHeads.mutex.Lock() + a.logs.mutex.Lock() + a.newPendingTxs.mutex.Lock() + a.syncing.mutex.Lock() + } +} + +func (a *Agent) unlockAllRegistries(readOnly bool) { + if readOnly { + a.newHeads.mutex.RUnlock() + a.logs.mutex.RUnlock() + a.newPendingTxs.mutex.RUnlock() + a.syncing.mutex.RUnlock() + } else { + a.newHeads.mutex.Unlock() + a.logs.mutex.Unlock() + a.newPendingTxs.mutex.Unlock() + a.syncing.mutex.Unlock() + } +} + +func (a *Agent) subscriptionCount(acquireLocks bool) int { + if acquireLocks { + a.lockAllRegistries(true) + defer a.unlockAllRegistries(true) + } + + return a.newHeads.subscriptionCount + + a.logs.subscriptionCount + + a.newPendingTxs.subscriptionCount + + a.syncing.subscriptionCount +} + +func (a *Agent) unsubscribe(id string) { + removeSubscription(id, a.newHeads) + removeSubscription(id, a.logs) + removeSubscription(id, a.newPendingTxs) + removeSubscription(id, a.syncing) +} + +func addSubscription(subscription *subscriptionInformation, registry *subscriptionRegistry) { + registry.mutex.Lock() + defer registry.mutex.Unlock() + + _, collision := registry.subscriptions[subscription.id] + registry.subscriptions[subscription.id] = subscription + if !collision { + registry.subscriptionCount = registry.subscriptionCount + 1 + } + + go subscription.run() +} + +func removeSubscription(id string, registry *subscriptionRegistry) { + registry.mutex.RLock() + sub, exists := registry.subscriptions[id] + registry.mutex.RUnlock() + if exists { + registry.mutex.Lock() + _, exists = registry.subscriptions[id] + if exists { + delete(registry.subscriptions, id) + registry.subscriptionCount = registry.subscriptionCount - 1 + } + registry.mutex.Unlock() + } + + if sub != nil { + sub.cancelFunc() + } +} + +func (a *Agent) NewSubscription(notifier *Notifier, params *eth.EthSubscriptionRequest) (string, error) { + subscription, err := notifier.Subscribe(a.unsubscribe) + if err != nil { + return "", err + } + + wrappedContext, cancel := context.WithCancel(notifier.Context()) + + wrappedSubscription := &subscriptionInformation{ + subscription, + params, + sync.RWMutex{}, + wrappedContext, + cancel, + false, + a.qtum, + } + + switch strings.ToLower(params.Method) { + case "logs": + addSubscription(wrappedSubscription, a.logs) + case "newheads": + addSubscription(wrappedSubscription, a.newHeads) + case "newpendingtransactions": + addSubscription(wrappedSubscription, a.newPendingTxs) + case "syncing": + addSubscription(wrappedSubscription, a.syncing) + default: + return "", errors.New(fmt.Sprintf("Unknown subscription type %s", params.Method)) + } + + a.mutex.RLock() + if !a.running { + // start processing subscriptions if nothing is running + // only one routine will run at once so if multiple startup they will exit so only one runs + go a.run() + } + a.mutex.RUnlock() + + return subscription.id, nil +} + +func (a *Agent) run() { + a.mutex.Lock() + if a.running { + a.mutex.Unlock() + return + } + a.running = true + a.mutex.Unlock() + + defer func() { + a.mutex.Lock() + defer a.mutex.Unlock() + + a.running = false + }() + + lastBlock := int64(0) + + draining := true + for draining { + select { + case <-a.stop: + // drain + default: + draining = false + } + } + + return + + for { + // infinite loop while we have subscriptions + subscriptionCount := a.subscriptionCount(true) + if subscriptionCount == 0 { + return + } + + blockchainInfo, err := a.qtum.GetBlockChainInfo() + if err != nil { + latestBlock := blockchainInfo.Blocks + if latestBlock > lastBlock { + + } + } + + select { + case <-time.After(10 * time.Second): + // continue + case <-a.stop: + return + } + } +} diff --git a/pkg/notifier/notifier.go b/pkg/notifier/notifier.go new file mode 100644 index 00000000..f859fa58 --- /dev/null +++ b/pkg/notifier/notifier.go @@ -0,0 +1,169 @@ +package notifier + +import ( + "context" + "crypto/rand" + "encoding/hex" + "encoding/json" + "sync" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/pkg/errors" +) + +var UnsubSignal = new(struct{}) + +type UnsubscribeCallback func(string) + +type Subscription struct { + id string + once sync.Once + unsubscribe UnsubscribeCallback + notifier *Notifier +} + +func NewSubscription(notifier *Notifier, callback UnsubscribeCallback) (*Subscription, error) { + id, err := getRandomSubscriptionId() + if err != nil { + return nil, err + } + return &Subscription{ + id: id, + once: sync.Once{}, + unsubscribe: callback, + notifier: notifier, + }, nil +} + +func getRandomSubscriptionId() (string, error) { + var subid [16]byte + n, _ := rand.Read(subid[:]) + if n != 16 { + return "", errors.New("Unable to generate subscription id") + } + return "0x" + hex.EncodeToString(subid[:]), nil +} + +func (s *Subscription) Unsubscribe() { + s.once.Do(func() { + s.unsubscribe(s.id) + }) +} + +type Notifier struct { + runMutex sync.Mutex + mutex sync.Mutex + ctx context.Context + close func() + send func(interface{}) error + logger log.Logger + queue chan interface{} + subscriptionIdPending *chan interface{} + subscriptionsFlushed *chan interface{} + subscriptions map[string]*Subscription +} + +func NewNotifier(ctx context.Context, close func(), send func(interface{}) error, logger log.Logger) *Notifier { + pending := make(chan interface{}) + flushed := make(chan interface{}) + return &Notifier{ + runMutex: sync.Mutex{}, + mutex: sync.Mutex{}, + ctx: ctx, + close: close, + send: send, + logger: log.WithPrefix(logger, "component", "notifier"), + queue: make(chan interface{}), + subscriptionIdPending: &pending, + subscriptionsFlushed: &flushed, + subscriptions: make(map[string]*Subscription), + } +} + +func (n *Notifier) Context() context.Context { + return n.ctx +} + +func (n *Notifier) Subscribe(unsubscribeCallback UnsubscribeCallback) (*Subscription, error) { + sub, err := NewSubscription(n, unsubscribeCallback) + if err != nil { + return nil, err + } + + return sub, nil +} + +func (n *Notifier) ResponseSent() { + n.mutex.Lock() + defer n.mutex.Unlock() + if n.subscriptionIdPending != nil { + close(*n.subscriptionIdPending) + n.subscriptionIdPending = nil + } +} + +func (n *Notifier) ResponseRequired() { + pending := make(chan interface{}) + n.subscriptionIdPending = &pending +} + +func (n *Notifier) Send(event interface{}) { + n.queue <- event +} + +func (n *Notifier) closeSubscriptionsFlushed() { + if n.subscriptionsFlushed != nil { + close(*n.subscriptionsFlushed) + n.subscriptionsFlushed = nil + } +} + +func (n *Notifier) Run() { + n.runMutex.Lock() + defer n.runMutex.Unlock() + + log.With(level.Debug(n.logger)).Log("msg", "Entering notifier loop") + + defer func() { + n.mutex.Lock() + defer n.mutex.Unlock() + defer func() { + log.With(level.Debug(n.logger)).Log("msg", "Notifier loop exited") + }() + + n.close() + close(n.queue) + n.closeSubscriptionsFlushed() + for _, sub := range n.subscriptions { + sub.Unsubscribe() + } + }() + + for { + select { + case <-n.ctx.Done(): + return + case event := <-n.queue: + log.With(level.Debug(n.logger)).Log("msg", event) + <-*n.subscriptionIdPending + if event == UnsubSignal { + n.mutex.Lock() + n.closeSubscriptionsFlushed() + n.mutex.Unlock() + } else { + bytes, err := json.Marshal(event) + if err != nil { + panic(err) + } + err = n.send(bytes) + if err != nil { + // write failure, close connection and unsubscribe + log.With(level.Debug(n.logger)).Log("msg", "Error writing response to websocket, closing it", "err", err) + n.close() + return + } + } + } + } +} diff --git a/pkg/qtum/client.go b/pkg/qtum/client.go index ca3242c3..7f138750 100644 --- a/pkg/qtum/client.go +++ b/pkg/qtum/client.go @@ -2,6 +2,7 @@ package qtum import ( "bytes" + "context" "encoding/json" "fmt" "io" @@ -87,6 +88,10 @@ func (c *Client) IsMain() bool { } func (c *Client) Request(method string, params interface{}, result interface{}) error { + return c.RequestWithContext(nil, method, params, result) +} + +func (c *Client) RequestWithContext(ctx context.Context, method string, params interface{}, result interface{}) error { req, err := c.NewRPCRequest(method, params) if err != nil { return errors.WithMessage(err, "couldn't make new rpc request") @@ -95,7 +100,7 @@ func (c *Client) Request(method string, params interface{}, result interface{}) var resp *SuccessJSONRPCResult max := int(math.Floor(math.Max(float64(maximumRequestTime/int(maximumBackoff)), 1))) for i := 0; i < max; i++ { - resp, err = c.Do(req) + resp, err = c.Do(ctx, req) if err != nil { if strings.Contains(err.Error(), ErrQtumWorkQueueDepth.Error()) && i != max-1 { requestString := marshalToString(req) @@ -122,7 +127,7 @@ func (c *Client) Request(method string, params interface{}, result interface{}) return nil } -func (c *Client) Do(req *JSONRPCRequest) (*SuccessJSONRPCResult, error) { +func (c *Client) Do(ctx context.Context, req *JSONRPCRequest) (*SuccessJSONRPCResult, error) { reqBody, err := json.MarshalIndent(req, "", " ") if err != nil { return nil, err @@ -136,7 +141,7 @@ func (c *Client) Do(req *JSONRPCRequest) (*SuccessJSONRPCResult, error) { fmt.Printf("=> qtum RPC request\n%s\n", reqBody) } - respBody, err := c.do(bytes.NewReader(reqBody)) + respBody, err := c.do(ctx, bytes.NewReader(reqBody)) if err != nil { return nil, errors.Wrap(err, "Client#do") } @@ -192,8 +197,14 @@ func (c *Client) NewRPCRequest(method string, params interface{}) (*JSONRPCReque }, nil } -func (c *Client) do(body io.Reader) ([]byte, error) { - req, err := http.NewRequest(http.MethodPost, c.URL, body) +func (c *Client) do(ctx context.Context, body io.Reader) ([]byte, error) { + var req *http.Request + var err error + if ctx != nil { + req, err = http.NewRequestWithContext(ctx, http.MethodPost, c.URL, body) + } else { + req, err = http.NewRequest(http.MethodPost, c.URL, body) + } if err != nil { return nil, err } diff --git a/pkg/qtum/method.go b/pkg/qtum/method.go index 5eabdf73..b094012a 100644 --- a/pkg/qtum/method.go +++ b/pkg/qtum/method.go @@ -1,6 +1,7 @@ package qtum import ( + "context" "encoding/json" "math/big" @@ -417,3 +418,20 @@ func (m *Method) GetNetworkInfo() (resp *NetworkInfoResponse, err error) { } return } + +func (m *Method) WaitForLogs(req *WaitForLogsRequest) (resp *WaitForLogsResponse, err error) { + return m.WaitForLogsWithContext(nil, req) +} + +func (m *Method) WaitForLogsWithContext(ctx context.Context, req *WaitForLogsRequest) (resp *WaitForLogsResponse, err error) { + if err := m.RequestWithContext(ctx, MethodWaitForLogs, req, &resp); err != nil { + if m.IsDebugEnabled() { + m.GetDebugLogger().Log("function", "WaitForLogs", "error", err) + } + return nil, err + } + if m.IsDebugEnabled() { + m.GetDebugLogger().Log("function", "WaitForLogs", "request", marshalToString(req), "msg", "Successfully got waitforlogs response") + } + return +} diff --git a/pkg/qtum/rpc_types.go b/pkg/qtum/rpc_types.go index f1d6bf60..aedbe1e3 100644 --- a/pkg/qtum/rpc_types.go +++ b/pkg/qtum/rpc_types.go @@ -1639,3 +1639,39 @@ type ( Score int64 `json:"score"` } ) + +// ========= waitforlogs ========== // +type ( + WaitForLogsRequest struct { + FromBlock interface{} `json:"fromBlock"` + ToBlock interface{} `json:"toBlock` + Filter WaitForLogsFilter `json:"filter"` + MinimumConfirmations int64 `json:"miniconf"` + } + + WaitForLogsFilter struct { + Addresses *[]string `json:"addresses,omitempty"` + Topics *[]interface{} `json:"topics,omitempty"` + } + + WaitForLogsResponse struct { + Entries []TransactionReceipt `json:"entries"` + Count int64 `json:"count"` + NextBlock int64 `json:"nextBlock"` + } +) + +func (r *WaitForLogsRequest) MarshalJSON() ([]byte, error) { + /* + 1. fromBlock (int | "latest", optional, default=null) The block number to start looking for logs. () + 2. toBlock (int | "latest", optional, default=null) The block number to stop looking for logs. If null, will wait indefinitely into the future. + 3. filter ({ addresses?: Hex160String[], topics?: Hex256String[] }, optional default={}) Filter conditions for logs. Addresses and topics are specified as array of hexadecimal strings + 4. minconf (uint, optional, default=6) Minimal number of confirmations before a log is returned + */ + return json.Marshal([]interface{}{ + r.FromBlock, + r.ToBlock, + r.Filter, + r.MinimumConfirmations, + }) +} diff --git a/pkg/server/handler.go b/pkg/server/handler.go index 82aeca96..4ef3c70b 100644 --- a/pkg/server/handler.go +++ b/pkg/server/handler.go @@ -4,10 +4,11 @@ import ( "encoding/json" stdLog "log" - "github.com/go-kit/kit/log/level" "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" + "github.com/qtumproject/janus/pkg/notifier" + "golang.org/x/net/websocket" ) func httpHandler(c echo.Context) error { @@ -25,16 +26,16 @@ func httpHandler(c echo.Context) error { cc.rpcReq = rpcReq - level.Info(cc.logger).Log("msg", "proxy RPC", "method", rpcReq.Method) + cc.GetLogger().Log("msg", "proxy RPC", "method", rpcReq.Method) // level.Debug(cc.logger).Log("msg", "before call transformer#Transform") - result, err := cc.transformer.Transform(rpcReq) + result, err := cc.transformer.Transform(rpcReq, c) // level.Debug(cc.logger).Log("msg", "after call transformer#Transform") if err != nil { err1 := errors.Cause(err) if err != err1 { - level.Error(cc.logger).Log("err", err.Error()) + cc.GetErrorLogger().Log("err", err.Error()) return cc.JSONRPCError(ð.JSONRPCError{ Code: 100, Message: err1.Error(), @@ -52,16 +53,247 @@ func httpHandler(c echo.Context) error { return cc.JSONRPCResult(result) } +/* +// subscription topic name is a random hex number +// unsubscribe +{"id": 1, "method": "eth_unsubscribe", "params": ["0x9cef478923ff08bf67fde6c64013158d"]} +=> +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +// new heads +{ + "id": 1, + "method": "eth_subscribe", + "params": [ + "newHeads" + ] +} +=> +{ + "jsonrpc": "2.0", + "id": 2, + "result": "0x9ce59a13059e417087c02d3236a0b1cc" +} +=> +{ + "jsonrpc": "2.0", + "method": "eth_subscription", + "params": { + "result": { + "difficulty": "0x15d9223a23aa", + "extraData": "0xd983010305844765746887676f312e342e328777696e646f7773", + "gasLimit": "0x47e7c4", + "gasUsed": "0x38658", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", + "nonce": "0x084149998194cc5f", + "number": "0x1348c9", + "parentHash": "0x7736fab79e05dc611604d22470dadad26f56fe494421b5b333de816ce1f25701", + "receiptRoot": "0x2fab35823ad00c7bb388595cb46652fe7886e00660a01e867824d3dceb1c8d36", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xb3346685172db67de536d8765c43c31009d0eb3bd9c501c9be3229203f15f378", + "timestamp": "0x56ffeff8", + "transactionsRoot": "0x0167ffa60e3ebc0b080cdb95f7c0087dd6c0e61413140e39d94d3468d7c9689f" + }, + "subscription": "0x9ce59a13059e417087c02d3236a0b1cc" + } +} +// logs +{ + "id": 1, + "method": "eth_subscribe", + "params": [ + "logs", + { + "address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd", + "topics": [ + "0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902" + ] + } + ] +} +=> +{ + "jsonrpc": "2.0", + "id": 2, + "result": "0x4a8a4c0517381924f9838102c5a4dcb7" +} +=> +{ + "jsonrpc": "2.0", + "method": "eth_subscription", + "params": { + "subscription": "0x4a8a4c0517381924f9838102c5a4dcb7", + "result": { + "address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd", + "blockHash": "0x61cdb2a09ab99abf791d474f20c2ea89bf8de2923a2d42bb49944c8c993cbf04", + "blockNumber": "0x29e87", + "data": "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003", + "logIndex": "0x0", + "topics": [ + "0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902" + ], + "transactionHash": "0xe044554a0a55067caafd07f8020ab9f2af60bdfe337e395ecd84b4877a3d1ab4", + "transactionIndex": "0x0" + } + } +} +// new pending transactions +{ + "id": 1, + "method": "eth_subscribe", + "params": [ + "newPendingTransactions" + ] +} +=> +{ + "jsonrpc": "2.0", + "id": 2, + "result": "0xc3b33aa549fb9a60e95d21862596617c" +} +=> +{ + "jsonrpc": "2.0", + "method": "eth_subscription", + "params": { + "subscription": "0xc3b33aa549fb9a60e95d21862596617c", + "result": "0xd6fdc5cc41a9959e922f30cb772a9aef46f4daea279307bc5f7024edc4ccd7fa" + } +} +// syncing +{ + "id": 1, + "method": "eth_subscribe", + "params": [ + "syncing" + ] +} +=> +{ + "jsonrpc": "2.0", + "id": 2, + "result": "0xe2ffeb2703bcf602d42922385829ce96" +} +=> +{ + "subscription": "0xe2ffeb2703bcf602d42922385829ce96", + "result": { + "syncing": true, + "status": { + "startingBlock": 674427, + "currentBlock": 67400, + "highestBlock": 674432, + "pulledStates": 0, + "knownStates": 0 + } + } +} +*/ + +func websocketHandler(c echo.Context) error { + myctx := c.Get("myctx") + cc, ok := myctx.(*myCtx) + if !ok { + return errors.New("Could not find myctx") + } + + cc.GetDebugLogger().Log("msg", "Got websocket request... opening") + req := c.Request() + req.Header.Set("Origin", "http://localhost:23888") + + websocket.Handler(func(ws *websocket.Conn) { + cc.GetDebugLogger().Log("msg", "opened websocket") + notifier := notifier.NewNotifier( + c.Request().Context(), + func() { + ws.Close() + }, func(value interface{}) error { + return websocket.Message.Send(ws, value) + }, + cc.GetLogger(), + ) + c.Set("notifier", notifier) + defer ws.Close() + defer func() { + cc.GetDebugLogger().Log("msg", "Websocket connection closed") + }() + go notifier.Run() + + for { + cc.GetDebugLogger().Log("msg", "reading websocket request") + // Read + var payload string + err := websocket.Message.Receive(ws, &payload) + if err != nil { + c.Logger().Error(err) + return + } + + var rpcReq eth.JSONRPCRequest + json.Unmarshal([]byte(payload), &rpcReq) + + cc.rpcReq = &rpcReq + + result, err := cc.transformer.Transform(&rpcReq, c) + + response := result + + if err != nil { + err1 := errors.Cause(err) + if err != err1 { + cc.GetErrorLogger().Log("err", err.Error()) + response = cc.GetJSONRPCError(ð.JSONRPCError{ + Code: 100, + Message: err1.Error(), + }) + } + } + + // Allow transformer to return an explicit JSON error + if jerr, isJSONErr := response.(*eth.JSONRPCError); isJSONErr { + response = cc.GetJSONRPCError(jerr) + } else { + response, err = cc.GetJSONRPCResult(response) + if err != nil { + cc.GetErrorLogger().Log("err", err.Error()) + return + } + } + + responseBytes, err := json.Marshal(response) + if err != nil { + cc.GetErrorLogger().Log("err", err.Error()) + return + } + + cc.GetDebugLogger().Log("response", string(responseBytes)) + + err = websocket.Message.Send(ws, string(responseBytes)) + if err == nil { + notifier.ResponseSent() + } else { + cc.GetErrorLogger().Log("err", err.Error()) + return + } + } + }).ServeHTTP(c.Response(), c.Request()) + return nil +} + func errorHandler(err error, c echo.Context) { myctx := c.Get("myctx") cc, ok := myctx.(*myCtx) if ok { - level.Error(cc.logger).Log("err", err.Error()) + cc.GetErrorLogger().Log("err", err.Error()) if err := cc.JSONRPCError(ð.JSONRPCError{ Code: 100, Message: err.Error(), }); err != nil { - level.Error(cc.logger).Log("msg", "reply to client", "err", err.Error()) + cc.GetErrorLogger().Log("msg", "reply to client", "err", err.Error()) } return } diff --git a/pkg/server/myctx.go b/pkg/server/myctx.go index 32a3e301..af64020b 100644 --- a/pkg/server/myctx.go +++ b/pkg/server/myctx.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/transformer" @@ -17,8 +18,12 @@ type myCtx struct { transformer *transformer.Transformer } +func (c *myCtx) GetJSONRPCResult(result interface{}) (*eth.JSONRPCResult, error) { + return eth.NewJSONRPCResult(c.rpcReq.ID, result) +} + func (c *myCtx) JSONRPCResult(result interface{}) error { - response, err := eth.NewJSONRPCResult(c.rpcReq.ID, result) + response, err := c.GetJSONRPCResult(result) if err != nil { return err } @@ -26,16 +31,20 @@ func (c *myCtx) JSONRPCResult(result interface{}) error { return c.JSON(http.StatusOK, response) } -func (c *myCtx) JSONRPCError(err *eth.JSONRPCError) error { +func (c *myCtx) GetJSONRPCError(err *eth.JSONRPCError) *eth.JSONRPCResult { var id json.RawMessage if c.rpcReq != nil && c.rpcReq.ID != nil { id = c.rpcReq.ID } - resp := ð.JSONRPCResult{ + return ð.JSONRPCResult{ ID: id, Error: err, JSONRPC: eth.RPCVersion, } +} + +func (c *myCtx) JSONRPCError(err *eth.JSONRPCError) error { + resp := c.GetJSONRPCError(err) if !c.Response().Committed { return c.JSON(http.StatusInternalServerError, resp) @@ -43,3 +52,26 @@ func (c *myCtx) JSONRPCError(err *eth.JSONRPCError) error { return nil } + +func (c *myCtx) SetLogger(l log.Logger) { + c.logger = log.WithPrefix(l, "component", "context") +} + +func (c *myCtx) GetLogger() log.Logger { + return c.logger +} + +func (c *myCtx) GetDebugLogger() log.Logger { + if !c.IsDebugEnabled() { + return log.NewNopLogger() + } + return log.With(level.Debug(c.logger)) +} + +func (c *myCtx) GetErrorLogger() log.Logger { + return log.With(level.Error(c.logger)) +} + +func (c *myCtx) IsDebugEnabled() bool { + return c.transformer.IsDebugEnabled() +} diff --git a/pkg/server/server.go b/pkg/server/server.go index 9f808e9b..50e2c857 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -66,7 +66,7 @@ func (s *Server) Start() error { } if s.debug { - level.Debug(cc.logger).Log("msg", "ETH RPC") + cc.GetDebugLogger().Log("msg", "ETH RPC") reqBody, err := qtum.ReformatJSON(req) resBody, err := qtum.ReformatJSON(res) @@ -98,6 +98,7 @@ func (s *Server) Start() error { e.HideBanner = true if s.mutex == nil { e.POST("/*", httpHandler) + e.GET("/ws", websocketHandler) } else { level.Info(s.logger).Log("msg", "Processing RPC requests single threaded") e.POST("/*", func(c echo.Context) error { @@ -105,6 +106,7 @@ func (s *Server) Start() error { defer s.mutex.Unlock() return httpHandler(c) }) + e.GET("/ws", websocketHandler) } https := (s.httpsKey != "" && s.httpsCert != "") @@ -170,7 +172,7 @@ func batchRequestsMiddleware(h echo.HandlerFunc) echo.HandlerFunc { } } isBatchRequests := func(msg json.RawMessage) bool { - return msg[0] == '[' + return len(msg) != 0 && msg[0] == '[' } c.Request().Body = ioutil.NopCloser(bytes.NewBuffer(reqBody)) // Reset diff --git a/pkg/transformer/eth_accounts.go b/pkg/transformer/eth_accounts.go index f1d8ba3d..d16d5757 100644 --- a/pkg/transformer/eth_accounts.go +++ b/pkg/transformer/eth_accounts.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" "github.com/qtumproject/janus/pkg/utils" @@ -15,7 +16,7 @@ func (p *ProxyETHAccounts) Method() string { return "eth_accounts" } -func (p *ProxyETHAccounts) Request(_ *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHAccounts) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return p.request() } diff --git a/pkg/transformer/eth_accounts_test.go b/pkg/transformer/eth_accounts_test.go index ea7178bc..2a136cde 100644 --- a/pkg/transformer/eth_accounts_test.go +++ b/pkg/transformer/eth_accounts_test.go @@ -36,7 +36,7 @@ func TestAccountRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHAccounts{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_blockNumber.go b/pkg/transformer/eth_blockNumber.go index 0bda1c16..d68a5450 100644 --- a/pkg/transformer/eth_blockNumber.go +++ b/pkg/transformer/eth_blockNumber.go @@ -2,6 +2,7 @@ package transformer import ( "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -15,7 +16,7 @@ func (p *ProxyETHBlockNumber) Method() string { return "eth_blockNumber" } -func (p *ProxyETHBlockNumber) Request(_ *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHBlockNumber) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return p.request() } diff --git a/pkg/transformer/eth_blockNumber_test.go b/pkg/transformer/eth_blockNumber_test.go index 1fb29768..01ce1cab 100644 --- a/pkg/transformer/eth_blockNumber_test.go +++ b/pkg/transformer/eth_blockNumber_test.go @@ -33,7 +33,7 @@ func TestBlockNumberRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHBlockNumber{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_call.go b/pkg/transformer/eth_call.go index 5442012c..7e3bdcd3 100644 --- a/pkg/transformer/eth_call.go +++ b/pkg/transformer/eth_call.go @@ -3,6 +3,7 @@ package transformer import ( "math/big" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" "github.com/qtumproject/janus/pkg/utils" @@ -17,7 +18,7 @@ func (p *ProxyETHCall) Method() string { return "eth_call" } -func (p *ProxyETHCall) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHCall) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.CallRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err diff --git a/pkg/transformer/eth_call_test.go b/pkg/transformer/eth_call_test.go index 57b26810..45a22ed7 100644 --- a/pkg/transformer/eth_call_test.go +++ b/pkg/transformer/eth_call_test.go @@ -73,7 +73,7 @@ func TestEthCallRequest(t *testing.T) { t.Fatal(err) } - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } @@ -170,7 +170,7 @@ func TestRetry(t *testing.T) { t.Fatal(err) } - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_chainId.go b/pkg/transformer/eth_chainId.go index 5ee26f0e..43236afa 100644 --- a/pkg/transformer/eth_chainId.go +++ b/pkg/transformer/eth_chainId.go @@ -4,6 +4,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -16,7 +17,7 @@ func (p *ProxyETHChainId) Method() string { return "eth_chainId" } -func (p *ProxyETHChainId) Request(req *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHChainId) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var qtumresp *qtum.GetBlockChainInfoResponse if err := p.Qtum.Request(qtum.MethodGetBlockChainInfo, nil, &qtumresp); err != nil { return nil, err diff --git a/pkg/transformer/eth_estimateGas.go b/pkg/transformer/eth_estimateGas.go index 72056cfe..3f2887d5 100644 --- a/pkg/transformer/eth_estimateGas.go +++ b/pkg/transformer/eth_estimateGas.go @@ -2,6 +2,7 @@ package transformer import ( "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -15,7 +16,7 @@ func (p *ProxyETHEstimateGas) Method() string { return "eth_estimateGas" } -func (p *ProxyETHEstimateGas) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHEstimateGas) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var ethreq eth.CallRequest if err := unmarshalRequest(rawreq.Params, ðreq); err != nil { return nil, err diff --git a/pkg/transformer/eth_estimateGas_test.go b/pkg/transformer/eth_estimateGas_test.go index 39d3cf16..9449cb4c 100644 --- a/pkg/transformer/eth_estimateGas_test.go +++ b/pkg/transformer/eth_estimateGas_test.go @@ -63,7 +63,7 @@ func TestEstimateGasRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHCall{qtumClient} proxyEthEstimateGas := ProxyETHEstimateGas{&proxyEth} - got, err := proxyEthEstimateGas.Request(requestRPC) + got, err := proxyEthEstimateGas.Request(requestRPC, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_gasPrice.go b/pkg/transformer/eth_gasPrice.go index a70a404b..373e162b 100644 --- a/pkg/transformer/eth_gasPrice.go +++ b/pkg/transformer/eth_gasPrice.go @@ -4,6 +4,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -17,7 +18,7 @@ func (p *ProxyETHGasPrice) Method() string { return "eth_gasPrice" } -func (p *ProxyETHGasPrice) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGasPrice) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { qtumresp, err := p.Qtum.GetGasPrice() if err != nil { return nil, err diff --git a/pkg/transformer/eth_gasPrice_test.go b/pkg/transformer/eth_gasPrice_test.go index bef7ff64..a8e95994 100644 --- a/pkg/transformer/eth_gasPrice_test.go +++ b/pkg/transformer/eth_gasPrice_test.go @@ -22,7 +22,7 @@ func TestGasPriceRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGasPrice{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getBalance.go b/pkg/transformer/eth_getBalance.go index bf63b5e4..b2215313 100644 --- a/pkg/transformer/eth_getBalance.go +++ b/pkg/transformer/eth_getBalance.go @@ -4,6 +4,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" "github.com/qtumproject/janus/pkg/utils" @@ -18,7 +19,7 @@ func (p *ProxyETHGetBalance) Method() string { return "eth_getBalance" } -func (p *ProxyETHGetBalance) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetBalance) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.GetBalanceRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err diff --git a/pkg/transformer/eth_getBalance_test.go b/pkg/transformer/eth_getBalance_test.go index 2164a7c4..718fd10e 100644 --- a/pkg/transformer/eth_getBalance_test.go +++ b/pkg/transformer/eth_getBalance_test.go @@ -49,7 +49,7 @@ func TestGetBalanceRequestAccount(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetBalance{qtumClient} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } @@ -100,7 +100,7 @@ func TestGetBalanceRequestContract(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetBalance{qtumClient} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getBlockByHash.go b/pkg/transformer/eth_getBlockByHash.go index 12d7b9f4..cdd8ec4f 100644 --- a/pkg/transformer/eth_getBlockByHash.go +++ b/pkg/transformer/eth_getBlockByHash.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -22,7 +23,7 @@ func (p *ProxyETHGetBlockByHash) Method() string { return "eth_getBlockByHash" } -func (p *ProxyETHGetBlockByHash) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetBlockByHash) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { req := new(eth.GetBlockByHashRequest) if err := unmarshalRequest(rawreq.Params, req); err != nil { return nil, err diff --git a/pkg/transformer/eth_getBlockByNumber.go b/pkg/transformer/eth_getBlockByNumber.go index af9fe01b..aa46c097 100644 --- a/pkg/transformer/eth_getBlockByNumber.go +++ b/pkg/transformer/eth_getBlockByNumber.go @@ -3,6 +3,7 @@ package transformer import ( "math/big" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -17,7 +18,7 @@ func (p *ProxyETHGetBlockByNumber) Method() string { return "eth_getBlockByNumber" } -func (p *ProxyETHGetBlockByNumber) Request(rpcReq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetBlockByNumber) Request(rpcReq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { req := new(eth.GetBlockByNumberRequest) if err := unmarshalRequest(rpcReq.Params, req); err != nil { return nil, errors.WithMessage(err, "couldn't unmarhsal rpc request") diff --git a/pkg/transformer/eth_getBlockByNumber_test.go b/pkg/transformer/eth_getBlockByNumber_test.go index 17fa152d..fe71f48c 100644 --- a/pkg/transformer/eth_getBlockByNumber_test.go +++ b/pkg/transformer/eth_getBlockByNumber_test.go @@ -48,7 +48,7 @@ func TestGetBlockByNumberUnknownBlockRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetBlockByNumber{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getCode.go b/pkg/transformer/eth_getCode.go index 998e8c9f..653f7b01 100644 --- a/pkg/transformer/eth_getCode.go +++ b/pkg/transformer/eth_getCode.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" "github.com/qtumproject/janus/pkg/utils" @@ -15,7 +16,7 @@ func (p *ProxyETHGetCode) Method() string { return "eth_getCode" } -func (p *ProxyETHGetCode) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetCode) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.GetCodeRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err diff --git a/pkg/transformer/eth_getCode_test.go b/pkg/transformer/eth_getCode_test.go index 18b26476..27ebed08 100644 --- a/pkg/transformer/eth_getCode_test.go +++ b/pkg/transformer/eth_getCode_test.go @@ -45,7 +45,7 @@ func TestGetAccountInfoRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetCode{qtumClient} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } @@ -87,7 +87,7 @@ func TestGetCodeInvalidAddressRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetCode{qtumClient} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getCompilers.go b/pkg/transformer/eth_getCompilers.go index b9685958..7578eff9 100644 --- a/pkg/transformer/eth_getCompilers.go +++ b/pkg/transformer/eth_getCompilers.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" ) @@ -11,7 +12,7 @@ func (p *ETHGetCompilers) Method() string { return "eth_getCompilers" } -func (p *ETHGetCompilers) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ETHGetCompilers) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { // hardcoded to empty return []string{}, nil } diff --git a/pkg/transformer/eth_getCompilers_test.go b/pkg/transformer/eth_getCompilers_test.go index 14be9017..525b34e4 100644 --- a/pkg/transformer/eth_getCompilers_test.go +++ b/pkg/transformer/eth_getCompilers_test.go @@ -15,7 +15,7 @@ func TestGetCompilersReturnsEmptyArray(t *testing.T) { } proxyEth := ETHGetCompilers{} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getFilterChanges.go b/pkg/transformer/eth_getFilterChanges.go index aafe9b00..d2f13133 100644 --- a/pkg/transformer/eth_getFilterChanges.go +++ b/pkg/transformer/eth_getFilterChanges.go @@ -4,6 +4,7 @@ import ( "encoding/json" "math/big" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" @@ -21,7 +22,7 @@ func (p *ProxyETHGetFilterChanges) Method() string { return "eth_getFilterChanges" } -func (p *ProxyETHGetFilterChanges) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetFilterChanges) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { filter, err := processFilter(p, rawreq) if err != nil { diff --git a/pkg/transformer/eth_getFilterChanges_test.go b/pkg/transformer/eth_getFilterChanges_test.go index 2a9571b0..ee2fcfee 100644 --- a/pkg/transformer/eth_getFilterChanges_test.go +++ b/pkg/transformer/eth_getFilterChanges_test.go @@ -49,7 +49,7 @@ func TestGetFilterChangesRequest_EmptyResult(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetFilterChanges{qtumClient, filterSimulator} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } @@ -95,7 +95,7 @@ func TestGetFilterChangesRequest_NoNewBlocks(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetFilterChanges{qtumClient, filterSimulator} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } @@ -128,7 +128,7 @@ func TestGetFilterChangesRequest_NoSuchFilter(t *testing.T) { //preparing proxy & executing request filterSimulator := eth.NewFilterSimulator() proxyEth := ProxyETHGetFilterChanges{qtumClient, filterSimulator} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) expectedErr := "Invalid filter id" if got != nil { diff --git a/pkg/transformer/eth_getFilterLogs.go b/pkg/transformer/eth_getFilterLogs.go index 325df4b4..32d902f9 100644 --- a/pkg/transformer/eth_getFilterLogs.go +++ b/pkg/transformer/eth_getFilterLogs.go @@ -1,9 +1,11 @@ package transformer import ( + "math/big" + + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" - "math/big" ) // ProxyETHGetFilterLogs implements ETHProxy @@ -15,7 +17,7 @@ func (p *ProxyETHGetFilterLogs) Method() string { return "eth_getFilterLogs" } -func (p *ProxyETHGetFilterLogs) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetFilterLogs) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { filter, err := processFilter(p.ProxyETHGetFilterChanges, rawreq) if err != nil { diff --git a/pkg/transformer/eth_getLogs.go b/pkg/transformer/eth_getLogs.go index 80248b17..6df5a079 100644 --- a/pkg/transformer/eth_getLogs.go +++ b/pkg/transformer/eth_getLogs.go @@ -3,6 +3,7 @@ package transformer import ( "encoding/json" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" "github.com/qtumproject/janus/pkg/utils" @@ -17,7 +18,7 @@ func (p *ProxyETHGetLogs) Method() string { return "eth_getLogs" } -func (p *ProxyETHGetLogs) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetLogs) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.GetLogsRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err @@ -86,7 +87,7 @@ func (p *ProxyETHGetLogs) ToRequest(ethreq *eth.GetLogsRequest) (*qtum.SearchLog } //transform EthReq topics to QtumReq topics: - topics, err := translateTopics(ethreq.Topics) + topics, err := eth.TranslateTopics(ethreq.Topics) if err != nil { return nil, err } diff --git a/pkg/transformer/eth_getLogs_test.go b/pkg/transformer/eth_getLogs_test.go index 05022bf2..28fd459b 100644 --- a/pkg/transformer/eth_getLogs_test.go +++ b/pkg/transformer/eth_getLogs_test.go @@ -77,7 +77,7 @@ func TestGetLogs(t *testing.T) { //preparing proxy & executing proxyEth := ProxyETHGetLogs{qtumClient} - got, err := proxyEth.Request(requestRPC) + got, err := proxyEth.Request(requestRPC, nil) if err != nil { t.Fatal(err) } @@ -122,7 +122,7 @@ func TestGetLogsTranslateTopicWorksWithNil(t *testing.T) { }, } - translatedTopics, err := translateTopics(request.Topics) + translatedTopics, err := eth.TranslateTopics(request.Topics) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getStorageAt.go b/pkg/transformer/eth_getStorageAt.go index 8320b690..b8d18ccb 100644 --- a/pkg/transformer/eth_getStorageAt.go +++ b/pkg/transformer/eth_getStorageAt.go @@ -3,6 +3,7 @@ package transformer import ( "fmt" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" "github.com/qtumproject/janus/pkg/utils" @@ -17,7 +18,7 @@ func (p *ProxyETHGetStorageAt) Method() string { return "eth_getStorageAt" } -func (p *ProxyETHGetStorageAt) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetStorageAt) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.GetStorageRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err diff --git a/pkg/transformer/eth_getStorageAt_test.go b/pkg/transformer/eth_getStorageAt_test.go index c0d7189b..200376f1 100644 --- a/pkg/transformer/eth_getStorageAt_test.go +++ b/pkg/transformer/eth_getStorageAt_test.go @@ -33,7 +33,7 @@ func TestGetStorageAtRequestWithNoLeadingZeros(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetStorageAt{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } @@ -74,7 +74,7 @@ func TestGetStorageAtRequestWithLeadingZeros(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetStorageAt{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } @@ -116,7 +116,7 @@ func TestGetStorageAtUnknownFieldRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetStorageAt{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getTransactionByBlockHashAndIndex.go b/pkg/transformer/eth_getTransactionByBlockHashAndIndex.go index afdac78b..d895dccc 100644 --- a/pkg/transformer/eth_getTransactionByBlockHashAndIndex.go +++ b/pkg/transformer/eth_getTransactionByBlockHashAndIndex.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -18,7 +19,7 @@ func (p *ProxyETHGetTransactionByBlockHashAndIndex) Method() string { return "eth_getTransactionByBlockHashAndIndex" } -func (p *ProxyETHGetTransactionByBlockHashAndIndex) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetTransactionByBlockHashAndIndex) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.GetTransactionByBlockHashAndIndex if err := json.Unmarshal(rawreq.Params, &req); err != nil { return nil, errors.Wrap(err, "couldn't unmarshal request") diff --git a/pkg/transformer/eth_getTransactionByBlockNumberAndIndex.go b/pkg/transformer/eth_getTransactionByBlockNumberAndIndex.go index 9ee9b0fb..159906c0 100644 --- a/pkg/transformer/eth_getTransactionByBlockNumberAndIndex.go +++ b/pkg/transformer/eth_getTransactionByBlockNumberAndIndex.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -18,7 +19,7 @@ func (p *ProxyETHGetTransactionByBlockNumberAndIndex) Method() string { return "eth_getTransactionByBlockNumberAndIndex" } -func (p *ProxyETHGetTransactionByBlockNumberAndIndex) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetTransactionByBlockNumberAndIndex) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.GetTransactionByBlockNumberAndIndex if err := json.Unmarshal(rawreq.Params, &req); err != nil { return nil, errors.Wrap(err, "couldn't unmarshal request") diff --git a/pkg/transformer/eth_getTransactionByHash.go b/pkg/transformer/eth_getTransactionByHash.go index f901b989..585794b8 100644 --- a/pkg/transformer/eth_getTransactionByHash.go +++ b/pkg/transformer/eth_getTransactionByHash.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -19,7 +20,7 @@ func (p *ProxyETHGetTransactionByHash) Method() string { return "eth_getTransactionByHash" } -func (p *ProxyETHGetTransactionByHash) Request(req *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetTransactionByHash) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var txHash eth.GetTransactionByHashRequest if err := json.Unmarshal(req.Params, &txHash); err != nil { return nil, errors.Wrap(err, "couldn't unmarshal request") diff --git a/pkg/transformer/eth_getTransactionByHash_test.go b/pkg/transformer/eth_getTransactionByHash_test.go index 6d65b053..25692d52 100644 --- a/pkg/transformer/eth_getTransactionByHash_test.go +++ b/pkg/transformer/eth_getTransactionByHash_test.go @@ -24,7 +24,7 @@ func TestGetTransactionByHashRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHGetTransactionByHash{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getTransactionCount.go b/pkg/transformer/eth_getTransactionCount.go index 7bdad9dd..bbf44139 100644 --- a/pkg/transformer/eth_getTransactionCount.go +++ b/pkg/transformer/eth_getTransactionCount.go @@ -4,6 +4,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -17,7 +18,7 @@ func (p *ProxyETHTxCount) Method() string { return "eth_getTransactionCount" } -func (p *ProxyETHTxCount) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHTxCount) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { /* not sure we need this. Need to figure out how to best unmarshal this in the future. For now this will work. var req eth.GetTransactionCountRequest diff --git a/pkg/transformer/eth_getTransactionCount_test.go b/pkg/transformer/eth_getTransactionCount_test.go index ce3c1db9..f2182ae6 100644 --- a/pkg/transformer/eth_getTransactionCount_test.go +++ b/pkg/transformer/eth_getTransactionCount_test.go @@ -22,7 +22,7 @@ func TestGetTransactionCountRequest(t *testing.T) { //preparing proxy & executing request proxyEth := ProxyETHTxCount{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_getTransactionReceipt.go b/pkg/transformer/eth_getTransactionReceipt.go index 35479001..e469af73 100644 --- a/pkg/transformer/eth_getTransactionReceipt.go +++ b/pkg/transformer/eth_getTransactionReceipt.go @@ -2,6 +2,7 @@ package transformer import ( "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -17,7 +18,7 @@ func (p *ProxyETHGetTransactionReceipt) Method() string { return "eth_getTransactionReceipt" } -func (p *ProxyETHGetTransactionReceipt) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHGetTransactionReceipt) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.GetTransactionReceiptRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err diff --git a/pkg/transformer/eth_getUncleByBlockHashAndIndex.go b/pkg/transformer/eth_getUncleByBlockHashAndIndex.go index 5d49f052..dea331fa 100644 --- a/pkg/transformer/eth_getUncleByBlockHashAndIndex.go +++ b/pkg/transformer/eth_getUncleByBlockHashAndIndex.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" ) @@ -11,7 +12,7 @@ func (p *ETHGetUncleByBlockHashAndIndex) Method() string { return "eth_getUncleByBlockHashAndIndex" } -func (p *ETHGetUncleByBlockHashAndIndex) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ETHGetUncleByBlockHashAndIndex) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { // hardcoded to nil return nil, nil } diff --git a/pkg/transformer/eth_getUncleByBlockHashAndIndex_test.go b/pkg/transformer/eth_getUncleByBlockHashAndIndex_test.go index 75d0b14c..582d3c16 100644 --- a/pkg/transformer/eth_getUncleByBlockHashAndIndex_test.go +++ b/pkg/transformer/eth_getUncleByBlockHashAndIndex_test.go @@ -14,7 +14,7 @@ func TestGetUncleByBlockHashAndIndexReturnsNil(t *testing.T) { } proxyEth := ETHGetUncleByBlockHashAndIndex{} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_hashrate.go b/pkg/transformer/eth_hashrate.go index 63a0d2be..b96c39f9 100644 --- a/pkg/transformer/eth_hashrate.go +++ b/pkg/transformer/eth_hashrate.go @@ -4,6 +4,7 @@ import ( "math" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -17,7 +18,7 @@ func (p *ProxyETHHashrate) Method() string { return "eth_hashrate" } -func (p *ProxyETHHashrate) Request(_ *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHHashrate) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return p.request() } diff --git a/pkg/transformer/eth_hashrate_test.go b/pkg/transformer/eth_hashrate_test.go index 75a54950..539cf87e 100644 --- a/pkg/transformer/eth_hashrate_test.go +++ b/pkg/transformer/eth_hashrate_test.go @@ -35,7 +35,7 @@ func TestHashrateRequest(t *testing.T) { } proxyEth := ProxyETHHashrate{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_mining.go b/pkg/transformer/eth_mining.go index facbabe5..3bf48ba2 100644 --- a/pkg/transformer/eth_mining.go +++ b/pkg/transformer/eth_mining.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -14,7 +15,7 @@ func (p *ProxyETHMining) Method() string { return "eth_mining" } -func (p *ProxyETHMining) Request(_ *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHMining) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return p.request() } diff --git a/pkg/transformer/eth_mining_test.go b/pkg/transformer/eth_mining_test.go index e567d756..5e969418 100644 --- a/pkg/transformer/eth_mining_test.go +++ b/pkg/transformer/eth_mining_test.go @@ -30,7 +30,7 @@ func TestMiningRequest(t *testing.T) { } proxyEth := ProxyETHMining{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_net_listening.go b/pkg/transformer/eth_net_listening.go index 6c9a8725..05720c90 100644 --- a/pkg/transformer/eth_net_listening.go +++ b/pkg/transformer/eth_net_listening.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -14,7 +15,7 @@ func (p *ProxyNetListening) Method() string { return "net_listening" } -func (p *ProxyNetListening) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyNetListening) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { networkInfo, err := p.GetNetworkInfo() if err != nil { p.GetDebugLogger().Log("method", p.Method(), "msg", "Failed to query network info", "err", err) diff --git a/pkg/transformer/eth_net_listening_test.go b/pkg/transformer/eth_net_listening_test.go index 0fd2917c..eb08a27e 100644 --- a/pkg/transformer/eth_net_listening_test.go +++ b/pkg/transformer/eth_net_listening_test.go @@ -36,7 +36,7 @@ func testNetListeningRequest(t *testing.T, active bool) { } proxyEth := ProxyNetListening{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_net_peerCount.go b/pkg/transformer/eth_net_peerCount.go index e387d642..36014e7e 100644 --- a/pkg/transformer/eth_net_peerCount.go +++ b/pkg/transformer/eth_net_peerCount.go @@ -2,6 +2,7 @@ package transformer import ( "github.com/dcb9/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -15,7 +16,7 @@ func (p *ProxyNetPeerCount) Method() string { return "net_peerCount" } -func (p *ProxyNetPeerCount) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyNetPeerCount) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return p.request() } diff --git a/pkg/transformer/eth_net_peerCount_test.go b/pkg/transformer/eth_net_peerCount_test.go index d6f8445c..6b8369e8 100644 --- a/pkg/transformer/eth_net_peerCount_test.go +++ b/pkg/transformer/eth_net_peerCount_test.go @@ -44,7 +44,7 @@ func testPeerCountRequest(t *testing.T, clients int) { } proxyEth := ProxyNetPeerCount{qtumClient} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_net_version.go b/pkg/transformer/eth_net_version.go index b1c5044c..c08826cd 100644 --- a/pkg/transformer/eth_net_version.go +++ b/pkg/transformer/eth_net_version.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -14,7 +15,7 @@ func (p *ProxyETHNetVersion) Method() string { return "net_version" } -func (p *ProxyETHNetVersion) Request(_ *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHNetVersion) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return p.request() } diff --git a/pkg/transformer/eth_newBlockFilter.go b/pkg/transformer/eth_newBlockFilter.go index cf63f382..1e80e2b4 100644 --- a/pkg/transformer/eth_newBlockFilter.go +++ b/pkg/transformer/eth_newBlockFilter.go @@ -2,6 +2,7 @@ package transformer import ( "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -16,7 +17,7 @@ func (p *ProxyETHNewBlockFilter) Method() string { return "eth_newBlockFilter" } -func (p *ProxyETHNewBlockFilter) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHNewBlockFilter) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return p.request() } diff --git a/pkg/transformer/eth_newFilter.go b/pkg/transformer/eth_newFilter.go index 4ac7edc4..1d3aba14 100644 --- a/pkg/transformer/eth_newFilter.go +++ b/pkg/transformer/eth_newFilter.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/dcb9/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -18,7 +19,7 @@ func (p *ProxyETHNewFilter) Method() string { return "eth_newFilter" } -func (p *ProxyETHNewFilter) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHNewFilter) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.NewFilterRequest if err := json.Unmarshal(rawreq.Params, &req); err != nil { return nil, err @@ -45,7 +46,7 @@ func (p *ProxyETHNewFilter) request(ethreq *eth.NewFilterRequest) (*eth.NewFilte filter.Data.Store("toBlock", to.Uint64()) if len(ethreq.Topics) > 0 { - topics, err := translateTopics(ethreq.Topics) + topics, err := eth.TranslateTopics(ethreq.Topics) if err != nil { return nil, err } diff --git a/pkg/transformer/eth_personal_unlockAccount.go b/pkg/transformer/eth_personal_unlockAccount.go index 5fd17ffc..bc13bc6a 100644 --- a/pkg/transformer/eth_personal_unlockAccount.go +++ b/pkg/transformer/eth_personal_unlockAccount.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" ) @@ -11,6 +12,6 @@ func (p *ProxyETHPersonalUnlockAccount) Method() string { return "personal_unlockAccount" } -func (p *ProxyETHPersonalUnlockAccount) Request(req *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHPersonalUnlockAccount) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return eth.PersonalUnlockAccountResponse(true), nil } diff --git a/pkg/transformer/eth_protocolVersion.go b/pkg/transformer/eth_protocolVersion.go index f7f3bed3..b84f3c3b 100644 --- a/pkg/transformer/eth_protocolVersion.go +++ b/pkg/transformer/eth_protocolVersion.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" ) @@ -11,6 +12,6 @@ func (p *ETHProtocolVersion) Method() string { return "eth_protocolVersion" } -func (p *ETHProtocolVersion) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ETHProtocolVersion) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return "0x41", nil } diff --git a/pkg/transformer/eth_protocolVersion_test.go b/pkg/transformer/eth_protocolVersion_test.go index 60fb30cc..34990080 100644 --- a/pkg/transformer/eth_protocolVersion_test.go +++ b/pkg/transformer/eth_protocolVersion_test.go @@ -14,7 +14,7 @@ func TestProtocolVersionReturnsHardcodedValue(t *testing.T) { } proxyEth := ETHProtocolVersion{} - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatal(err) } diff --git a/pkg/transformer/eth_sendRawTransaction.go b/pkg/transformer/eth_sendRawTransaction.go index 076ee2cc..ed6bb87f 100644 --- a/pkg/transformer/eth_sendRawTransaction.go +++ b/pkg/transformer/eth_sendRawTransaction.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -18,7 +19,7 @@ func (p *ProxyETHSendRawTransaction) Method() string { return "eth_sendRawTransaction" } -func (p *ProxyETHSendRawTransaction) Request(req *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHSendRawTransaction) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var params eth.SendRawTransactionRequest if err := unmarshalRequest(req.Params, ¶ms); err != nil { return nil, err diff --git a/pkg/transformer/eth_sendTransaction.go b/pkg/transformer/eth_sendTransaction.go index 5ab216bf..495860b5 100644 --- a/pkg/transformer/eth_sendTransaction.go +++ b/pkg/transformer/eth_sendTransaction.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -17,7 +18,7 @@ func (p *ProxyETHSendTransaction) Method() string { return "eth_sendTransaction" } -func (p *ProxyETHSendTransaction) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHSendTransaction) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.SendTransactionRequest err := unmarshalRequest(rawreq.Params, &req) if err != nil { diff --git a/pkg/transformer/eth_sign.go b/pkg/transformer/eth_sign.go index af951430..312afa56 100644 --- a/pkg/transformer/eth_sign.go +++ b/pkg/transformer/eth_sign.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -22,7 +23,7 @@ func (p *ProxyETHSign) Method() string { return "eth_sign" } -func (p *ProxyETHSign) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHSign) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.SignRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { p.GetDebugLogger().Log("method", p.Method(), "error", err) diff --git a/pkg/transformer/eth_signTransaction.go b/pkg/transformer/eth_signTransaction.go index bb8fb6a5..697a5294 100644 --- a/pkg/transformer/eth_signTransaction.go +++ b/pkg/transformer/eth_signTransaction.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -20,7 +21,7 @@ func (p *ProxyETHSignTransaction) Method() string { return "eth_signTransaction" } -func (p *ProxyETHSignTransaction) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHSignTransaction) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.SendTransactionRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err diff --git a/pkg/transformer/eth_subscribe.go b/pkg/transformer/eth_subscribe.go new file mode 100644 index 00000000..a7fa453e --- /dev/null +++ b/pkg/transformer/eth_subscribe.go @@ -0,0 +1,52 @@ +package transformer + +import ( + "github.com/labstack/echo" + "github.com/pkg/errors" + "github.com/qtumproject/janus/pkg/eth" + "github.com/qtumproject/janus/pkg/notifier" + "github.com/qtumproject/janus/pkg/qtum" +) + +// ETHSubscribe implements ETHProxy +type ETHSubscribe struct { + *qtum.Qtum + *notifier.Agent +} + +func (p *ETHSubscribe) Method() string { + return "eth_subscribe" +} + +func (p *ETHSubscribe) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { + notifier := getNotifier(c) + if notifier == nil { + p.GetLogger().Log("msg", "eth_subscribe only supported over websocket") + /* + // TODO + { + "jsonrpc": "2.0", + "id": 580, + "error": { + "code": -32601, + "message": "The method eth_subscribe does not exist/is not available" + } + } + */ + return nil, errors.New("The method eth_subscribe does not exist/is not available") + } + + var req eth.EthSubscriptionRequest + if err := unmarshalRequest(rawreq.Params, &req); err != nil { + return nil, err + } + + return p.request(&req, notifier) +} + +func (p *ETHSubscribe) request(req *eth.EthSubscriptionRequest, notifier *notifier.Notifier) (*eth.EthSubscriptionResponse, error) { + notifier.ResponseRequired() + id, err := p.NewSubscription(notifier, req) + response := eth.EthSubscriptionResponse(id) + return &response, err +} diff --git a/pkg/transformer/eth_uninstallFilter.go b/pkg/transformer/eth_uninstallFilter.go index d43dbb48..5054969d 100644 --- a/pkg/transformer/eth_uninstallFilter.go +++ b/pkg/transformer/eth_uninstallFilter.go @@ -2,6 +2,7 @@ package transformer import ( "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" ) @@ -16,7 +17,7 @@ func (p *ProxyETHUninstallFilter) Method() string { return "eth_uninstallFilter" } -func (p *ProxyETHUninstallFilter) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyETHUninstallFilter) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var req eth.UninstallFilterRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { return nil, err diff --git a/pkg/transformer/notifier.go b/pkg/transformer/notifier.go new file mode 100644 index 00000000..8e3d9039 --- /dev/null +++ b/pkg/transformer/notifier.go @@ -0,0 +1,15 @@ +package transformer + +import ( + "github.com/labstack/echo" + "github.com/qtumproject/janus/pkg/notifier" +) + +func getNotifier(c echo.Context) *notifier.Notifier { + storedValue := c.Get("notifier") + notifier, ok := storedValue.(*notifier.Notifier) + if !ok { + return nil + } + return notifier +} diff --git a/pkg/transformer/qtum_getUTXOs.go b/pkg/transformer/qtum_getUTXOs.go index ba7d4954..29667c28 100644 --- a/pkg/transformer/qtum_getUTXOs.go +++ b/pkg/transformer/qtum_getUTXOs.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" "github.com/qtumproject/janus/pkg/qtum" @@ -18,7 +19,7 @@ func (p *ProxyQTUMGetUTXOs) Method() string { return "qtum_getUTXOs" } -func (p *ProxyQTUMGetUTXOs) Request(req *eth.JSONRPCRequest) (interface{}, error) { +func (p *ProxyQTUMGetUTXOs) Request(req *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var params eth.GetUTXOsRequest if err := unmarshalRequest(req.Params, ¶ms); err != nil { return nil, errors.WithMessage(err, "couldn't unmarshal request parameters") diff --git a/pkg/transformer/tests_common.go b/pkg/transformer/tests_common.go index 31f9557f..2dc9483b 100644 --- a/pkg/transformer/tests_common.go +++ b/pkg/transformer/tests_common.go @@ -491,7 +491,7 @@ func testETHProxyRequest(t *testing.T, initializer ETHProxyInitializer, requestP //preparing proxy & executing request proxyEth := initializer(qtumClient) - got, err := proxyEth.Request(request) + got, err := proxyEth.Request(request, nil) if err != nil { t.Fatalf("Failed to process request on %T.Request(%s): %s", proxyEth, requestParams, err) } diff --git a/pkg/transformer/transformer.go b/pkg/transformer/transformer.go index 5a1cc629..716cb826 100644 --- a/pkg/transformer/transformer.go +++ b/pkg/transformer/transformer.go @@ -2,8 +2,10 @@ package transformer import ( "github.com/go-kit/kit/log" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" + "github.com/qtumproject/janus/pkg/notifier" "github.com/qtumproject/janus/pkg/qtum" ) @@ -58,12 +60,12 @@ func (t *Transformer) Register(p ETHProxy) error { } // Transform takes a Transformer and transforms the request from ETH request and returns the proxy request -func (t *Transformer) Transform(req *eth.JSONRPCRequest) (interface{}, error) { +func (t *Transformer) Transform(req *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { proxy, err := t.getProxy(req.Method) if err != nil { return nil, errors.WithMessage(err, "couldn't get proxy") } - resp, err := proxy.Request(req) + resp, err := proxy.Request(req, c) if err != nil { return nil, errors.WithMessagef(err, "couldn't proxy %s request", req.Method) } @@ -78,9 +80,14 @@ func (t *Transformer) getProxy(method string) (ETHProxy, error) { return proxy, nil } +func (t *Transformer) IsDebugEnabled() bool { + return t.debugMode +} + // DefaultProxies are the default proxy methods made available func DefaultProxies(qtumRPCClient *qtum.Qtum) []ETHProxy { filter := eth.NewFilterSimulator() + agent := notifier.NewAgent(qtumRPCClient) getFilterChanges := &ProxyETHGetFilterChanges{Qtum: qtumRPCClient, filter: filter} ethCall := &ProxyETHCall{Qtum: qtumRPCClient} @@ -123,6 +130,8 @@ func DefaultProxies(qtumRPCClient *qtum.Qtum) []ETHProxy { &ProxyETHSignTransaction{Qtum: qtumRPCClient}, &ProxyETHSendRawTransaction{Qtum: qtumRPCClient}, + ÐSubscribe{Qtum: qtumRPCClient, Agent: agent}, + &ProxyQTUMGetUTXOs{Qtum: qtumRPCClient}, &ProxyNetPeerCount{Qtum: qtumRPCClient}, diff --git a/pkg/transformer/type.go b/pkg/transformer/type.go index ae4e615d..935d99e8 100644 --- a/pkg/transformer/type.go +++ b/pkg/transformer/type.go @@ -3,6 +3,7 @@ package transformer import ( "errors" + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" ) @@ -11,6 +12,6 @@ var UnmarshalRequestErr = errors.New("Input is invalid") type Option func(*Transformer) error type ETHProxy interface { - Request(*eth.JSONRPCRequest) (interface{}, error) + Request(*eth.JSONRPCRequest, echo.Context) (interface{}, error) Method() string } diff --git a/pkg/transformer/util.go b/pkg/transformer/util.go index 1abb63f3..85920cd8 100644 --- a/pkg/transformer/util.go +++ b/pkg/transformer/util.go @@ -301,35 +301,6 @@ func convertQtumAddress(address string) (ethAddress string, _ error) { return hex.EncodeToString(ethAddrBytes), nil } -// translateTopics takes in an ethReq's topics field and translates it to a it's equivalent QtumReq -// topics (optional) has a max lenght of 4 -func translateTopics(ethTopics []interface{}) ([]interface{}, error) { - - var topics []interface{} - - if len(ethTopics) > 4 { - return nil, errors.Errorf("invalid number of topics. Logs have a max of 4 topics.") - } - - for _, topic := range ethTopics { - switch topic.(type) { - case []interface{}: - topic, err := translateTopics(topic.([]interface{})) - if err != nil { - return nil, err - } - topics = append(topics, topic) - case string: - topics = append(topics, utils.RemoveHexPrefix(topic.(string))) - case nil: - topics = append(topics, nil) - } - } - - return topics, nil - -} - func processFilter(p *ProxyETHGetFilterChanges, rawreq *eth.JSONRPCRequest) (*eth.Filter, error) { var req eth.GetFilterChangesRequest if err := unmarshalRequest(rawreq.Params, &req); err != nil { diff --git a/pkg/transformer/web3_clientVersion.go b/pkg/transformer/web3_clientVersion.go index f3ad18ef..1d4cbffb 100644 --- a/pkg/transformer/web3_clientVersion.go +++ b/pkg/transformer/web3_clientVersion.go @@ -1,6 +1,7 @@ package transformer import ( + "github.com/labstack/echo" "github.com/qtumproject/janus/pkg/eth" ) @@ -13,7 +14,7 @@ func (p *Web3ClientVersion) Method() string { return "web3_clientVersion" } -func (p *Web3ClientVersion) Request(_ *eth.JSONRPCRequest) (interface{}, error) { +func (p *Web3ClientVersion) Request(_ *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { return "QTUM ETHTestRPC/ethereum-js", nil } diff --git a/pkg/transformer/web3_sha3.go b/pkg/transformer/web3_sha3.go index 15ea3644..74658e48 100644 --- a/pkg/transformer/web3_sha3.go +++ b/pkg/transformer/web3_sha3.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + "github.com/labstack/echo" "github.com/pkg/errors" "github.com/qtumproject/janus/pkg/eth" ) @@ -15,7 +16,7 @@ func (p *Web3Sha3) Method() string { return "web3_sha3" } -func (p *Web3Sha3) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) { +func (p *Web3Sha3) Request(rawreq *eth.JSONRPCRequest, c echo.Context) (interface{}, error) { var err error var req eth.Web3Sha3Request if err = json.Unmarshal(rawreq.Params, &req); err != nil { diff --git a/pkg/transformer/web3_sha3_test.go b/pkg/transformer/web3_sha3_test.go index 69824d86..bb808ccc 100644 --- a/pkg/transformer/web3_sha3_test.go +++ b/pkg/transformer/web3_sha3_test.go @@ -19,7 +19,7 @@ func TestWeb3Sha3Request(t *testing.T) { } web3Sha3 := Web3Sha3{} - got, err := web3Sha3.Request(request) + got, err := web3Sha3.Request(request, nil) if err != nil { t.Fatal(err) } @@ -48,7 +48,7 @@ func testWeb3Sha3Errors(t *testing.T, input []json.RawMessage, want string) { } web3Sha3 := Web3Sha3{} - got, err := web3Sha3.Request(request) + got, err := web3Sha3.Request(request, nil) if err == nil { t.Errorf( "Expected error\ninput: %s\nwant: %s\ngot: %s",