From 2ea42d03e4d14a6df322ad26ef5087982d7427de Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 13:54:10 +0200 Subject: [PATCH 01/15] log fix --- services/requester/requester.go | 42 ++++++++++++++------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/services/requester/requester.go b/services/requester/requester.go index d518805c5..8c3c589f5 100644 --- a/services/requester/requester.go +++ b/services/requester/requester.go @@ -11,7 +11,6 @@ import ( "github.com/onflow/cadence" "github.com/onflow/flow-go-sdk" - "github.com/onflow/flow-go-sdk/access" "github.com/onflow/flow-go-sdk/crypto" "github.com/onflow/flow-go/fvm/evm/stdlib" evmTypes "github.com/onflow/flow-go/fvm/evm/types" @@ -89,14 +88,14 @@ type Requester interface { var _ Requester = &EVM{} type EVM struct { - client access.Client + client *CrossSporkClient config *config.Config signer crypto.Signer logger zerolog.Logger } func NewEVM( - client access.Client, + client *CrossSporkClient, config *config.Config, signer crypto.Signer, logger zerolog.Logger, @@ -145,10 +144,6 @@ func NewEVM( } func (e *EVM) SendRawTransaction(ctx context.Context, data []byte) (common.Hash, error) { - e.logger.Debug(). - Str("data", fmt.Sprintf("%x", data)). - Msg("send raw transaction") - tx := &types.Transaction{} if err := tx.UnmarshalBinary(data); err != nil { return common.Hash{}, err @@ -167,6 +162,7 @@ func (e *EVM) SendRawTransaction(ctx context.Context, data []byte) (common.Hash, script := e.replaceAddresses(runTxScript) flowID, err := e.signAndSend(ctx, script, hexEncodedTx) if err != nil { + e.logger.Error().Err(err).Str("data", string(data)).Msg("failed to send transaction") return common.Hash{}, err } @@ -236,24 +232,22 @@ func (e *EVM) signAndSend(ctx context.Context, script []byte, args ...cadence.Va return flow.EmptyID, fmt.Errorf("failed to send transaction: %w", err) } - // this is only used for debugging purposes - if d := e.logger.Debug(); d.Enabled() { - go func(id flow.Identifier) { - res, _ := e.client.GetTransactionResult(context.Background(), id) - if res != nil && res.Error != nil { - e.logger.Error(). - Str("flow-id", id.String()). - Err(res.Error). - Msg("flow transaction failed to execute") - return - } - - e.logger.Debug(). + go func(id flow.Identifier) { + res, _ := e.client.GetTransactionResult(context.Background(), id) + if res != nil && res.Error != nil { + e.logger.Error(). Str("flow-id", id.String()). - Str("events", fmt.Sprintf("%v", res.Events)). - Msg("flow transaction executed successfully") - }(flowTx.ID()) - } + Err(res.Error). + Msg("flow transaction failed to execute") + return + } + + e.logger.Info(). + Str("flow-id", id.String()). + Str("events", fmt.Sprintf("%v", res.Events)). + Str("status", res.Status.String()). + Msg("flow transaction executed successfully") + }(flowTx.ID()) return flowTx.ID(), nil } From bbc59165f1b5e374d41c564d2a65a0d867a4c257 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 13:54:54 +0200 Subject: [PATCH 02/15] use x-spork client --- bootstrap/bootstrap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 6575c3a1a..50d6d310b 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -188,7 +188,7 @@ func startIngestion( func startServer( ctx context.Context, cfg *config.Config, - client access.Client, + client *requester.CrossSporkClient, blocks storage.BlockIndexer, transactions storage.TransactionIndexer, receipts storage.ReceiptIndexer, From 02e238f2b961b2c644d0827d1042c70b4c776d94 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 14:25:15 +0200 Subject: [PATCH 03/15] change x-spork client implementation to contain start/end range of heights --- services/requester/cross-spork_client.go | 131 +++++++++++++---------- 1 file changed, 77 insertions(+), 54 deletions(-) diff --git a/services/requester/cross-spork_client.go b/services/requester/cross-spork_client.go index f33093247..c200917e9 100644 --- a/services/requester/cross-spork_client.go +++ b/services/requester/cross-spork_client.go @@ -2,16 +2,28 @@ package requester import ( "context" + "errors" "fmt" "github.com/onflow/cadence" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/access" "github.com/rs/zerolog" - "golang.org/x/exp/maps" - "golang.org/x/exp/slices" ) +var ErrOutOfRange = errors.New("height is out of range for provided spork clients") + +type sporkClient struct { + firstHeight uint64 + lastHeight uint64 + client access.Client +} + +// contains checks if the provided height is withing the range of available heights +func (s *sporkClient) contains(height uint64) bool { + return height >= s.firstHeight && height <= s.lastHeight +} + // CrossSporkClient is a wrapper around the Flow AN client that can // access different AN APIs based on the height boundaries of the sporks. // @@ -21,10 +33,9 @@ import ( // Any API that supports cross-spork access must have a defined function // that shadows the original access Client function. type CrossSporkClient struct { - logger zerolog.Logger - // this map holds the last heights and clients for each spork - sporkClients map[uint64]access.Client - sporkBoundaries []uint64 + logger zerolog.Logger + sporkClients []*sporkClient + currentSporkFirstHeight uint64 access.Client } @@ -35,10 +46,16 @@ func NewCrossSporkClient( pastSporks []access.Client, logger zerolog.Logger, ) (*CrossSporkClient, error) { + info, err := currentSpork.GetNodeVersionInfo(context.Background()) + if err != nil { + return nil, err + } + client := &CrossSporkClient{ - logger: logger, - sporkClients: make(map[uint64]access.Client), - Client: currentSpork, + logger: logger, + sporkClients: make([]*sporkClient, 0), + currentSporkFirstHeight: info.NodeRootBlockHeight, + Client: currentSpork, } for _, sporkClient := range pastSporks { @@ -47,79 +64,79 @@ func NewCrossSporkClient( } } - // create a descending list of block heights that represent boundaries - // of each spork, after crossing each height, we use a different client - heights := maps.Keys(client.sporkClients) - slices.Sort(heights) - slices.Reverse(heights) // make it descending - client.sporkBoundaries = heights - return client, nil } -// addSpork will add a new spork host defined by the last height boundary in that spork. +// addSpork will add a new spork host defined by the first and last height boundary in that spork. func (c *CrossSporkClient) addSpork(client access.Client) error { header, err := client.GetLatestBlockHeader(context.Background(), true) if err != nil { return fmt.Errorf("could not get latest height using the spork client: %w", err) } - lastHeight := header.Height + info, err := client.GetNodeVersionInfo(context.Background()) + if err != nil { + return fmt.Errorf("could not get node info using the spork client: %w", err) + } - if _, ok := c.sporkClients[lastHeight]; ok { - return fmt.Errorf("provided last height already exists") + spork := &sporkClient{ + firstHeight: info.NodeRootBlockHeight, + lastHeight: header.Height, + client: client, } - c.sporkClients[lastHeight] = client + c.sporkClients = append(c.sporkClients, spork) c.logger.Info(). - Uint64("spork-boundary", lastHeight). - Msg("added spork specific client") + Uint64("spork-last-height", header.Height). + Uint64("spork-first-height", info.NodeRootBlockHeight). + Msg("added spork client") return nil } // IsPastSpork will check if the provided height is contained in the previous sporks. func (c *CrossSporkClient) IsPastSpork(height uint64) bool { - return len(c.sporkBoundaries) > 0 && height <= c.sporkBoundaries[0] + return height < c.currentSporkFirstHeight } -// getClientForHeight returns the client for the given height. It starts by using the current spork client, -// then iteratively checks the upper height boundaries in descending order and returns the last client -// that still contains the given height within its upper height limit. If no client is found, it returns -// the current spork client. -// Please note that even if a client for provided height is found we don't guarantee the data being available -// because it still might not have access to the height provided, because there might be other sporks with -// lower height boundaries that we didn't configure for. -// This would result in the error when using the client to access such data. -func (c *CrossSporkClient) getClientForHeight(height uint64) access.Client { - - // start by using the current spork client, then iterate all the upper height boundaries - // and find the last client that still contains the height in its upper height limit - client := c.Client - for _, upperBound := range c.sporkBoundaries { - if upperBound >= height { - client = c.sporkClients[upperBound] +// getClientForHeight returns the client for the given height that contains the height range. +// +// If the height is not contained in any of the past spork clients we return an error. +// If the height is contained in the current spork client we return the current spork client, +// but that doesn't guarantee the height will be found, since the height might be bigger than the +// latest height in the current spork, which is not checked due to performance reasons. +func (c *CrossSporkClient) getClientForHeight(height uint64) (access.Client, error) { + if !c.IsPastSpork(height) { + return c.Client, nil + } + for _, spork := range c.sporkClients { + if spork.contains(height) { c.logger.Debug(). - Uint64("spork-boundary", upperBound). + Uint64("requested-cadence-height", height). Msg("using previous spork client") + + return spork.client, nil } } - return client + // if not found return an error + return nil, ErrOutOfRange } // GetLatestHeightForSpork will determine the spork client in which the provided height is contained // and then find the latest height in that spork. func (c *CrossSporkClient) GetLatestHeightForSpork(ctx context.Context, height uint64) (uint64, error) { - block, err := c. - getClientForHeight(height). - GetLatestBlockHeader(ctx, true) + client, err := c.getClientForHeight(height) if err != nil { return 0, err } + block, err := client.GetLatestBlockHeader(ctx, true) + if err != nil { + return 0, err + } return block.Height, nil } @@ -127,9 +144,11 @@ func (c *CrossSporkClient) GetBlockHeaderByHeight( ctx context.Context, height uint64, ) (*flow.BlockHeader, error) { - return c. - getClientForHeight(height). - GetBlockHeaderByHeight(ctx, height) + client, err := c.getClientForHeight(height) + if err != nil { + return nil, err + } + return client.GetBlockHeaderByHeight(ctx, height) } func (c *CrossSporkClient) ExecuteScriptAtBlockHeight( @@ -138,9 +157,11 @@ func (c *CrossSporkClient) ExecuteScriptAtBlockHeight( script []byte, arguments []cadence.Value, ) (cadence.Value, error) { - return c. - getClientForHeight(height). - ExecuteScriptAtBlockHeight(ctx, height, script, arguments) + client, err := c.getClientForHeight(height) + if err != nil { + return nil, err + } + return client.ExecuteScriptAtBlockHeight(ctx, height, script, arguments) } func (c *CrossSporkClient) SubscribeEventsByBlockHeight( @@ -149,7 +170,9 @@ func (c *CrossSporkClient) SubscribeEventsByBlockHeight( filter flow.EventFilter, opts ...access.SubscribeOption, ) (<-chan flow.BlockEvents, <-chan error, error) { - return c. - getClientForHeight(startHeight). - SubscribeEventsByBlockHeight(ctx, startHeight, filter, opts...) + client, err := c.getClientForHeight(startHeight) + if err != nil { + return nil, nil, err + } + return client.SubscribeEventsByBlockHeight(ctx, startHeight, filter, opts...) } From eefb0d48855553798b9e07b0307943e259a89751 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 14:25:25 +0200 Subject: [PATCH 04/15] update go sdk --- go.mod | 2 +- go.sum | 8 ++++---- tests/go.mod | 2 +- tests/go.sum | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 56ed1880b..b5607dc8c 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/onflow/cadence v1.0.0-preview.29 github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd - github.com/onflow/flow-go-sdk v1.0.0-preview.30 + github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347 github.com/onflow/go-ethereum v1.13.4 github.com/rs/cors v1.8.0 github.com/rs/zerolog v1.31.0 diff --git a/go.sum b/go.sum index 383adb2a4..24c83e34c 100644 --- a/go.sum +++ b/go.sum @@ -1002,7 +1002,7 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= github.com/aws/aws-sdk-go-v2 v1.23.1/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA= -github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= +github.com/aws/aws-sdk-go-v2 v1.27.0 h1:7bZWKoXhzI+mMR/HjdMx8ZCC5+6fY0lS5tr0bbgiLlo= github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= github.com/aws/aws-sdk-go-v2/config v1.25.5/go.mod h1:Bf4gDvy4ZcFIK0rqDu1wp9wrubNba2DojiPB2rt6nvI= @@ -1024,7 +1024,7 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1x github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4/go.mod h1:aYCGNjyUCUelhofxlZyj63srdxWUSsBSGg5l6MCuXuE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 h1:Wx0rlZoEJR7JwlSZcHnEa7CNjrSIyVxMFWGAaXy4fJY= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.0 h1:HWsM0YQWX76V6MOp07YuTYacm8k7h69ObJuw7Nck+og= github.com/aws/aws-sdk-go-v2/service/kms v1.26.3/go.mod h1:N3++/sLV97B8Zliz7KRqNcojOX7iMBZWKiuit5FKtH0= github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= @@ -1885,8 +1885,8 @@ github.com/onflow/flow-ft/lib/go/templates v1.0.0/go.mod h1:uQ8XFqmMK2jxyBSVrmyu github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd h1:bSoQMARSC4dk6sQPv6SRkV7QvovKoNksTnydK9e5hL4= github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd/go.mod h1:5ysH9wggXlvJqbALEBZc2uNx6DIE+QsBoocuM8bSGC0= github.com/onflow/flow-go-sdk v1.0.0-M1/go.mod h1:TDW0MNuCs4SvqYRUzkbRnRmHQL1h4X8wURsCw9P9beo= -github.com/onflow/flow-go-sdk v1.0.0-preview.30 h1:62IwC7l8Uw1mxoZe7ewJII0HFHLUMsg04z1BW3JSEfM= -github.com/onflow/flow-go-sdk v1.0.0-preview.30/go.mod h1:PBIk3vLqU1aLdbWPw7ljRDmwSGLcsuk/ipL9eLMgWwc= +github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347 h1:qXJa8wp2aJLzDO5TVmMxaSHlrZ0/O/HMHzrpFUDP0eo= +github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347/go.mod h1:J4iKISX976mxV3ReTWiURG/ai50h61s2XJZ3YcK2lCg= github.com/onflow/flow-nft/lib/go/contracts v1.2.1 h1:woAAS5z651sDpi7ihAHll8NvRS9uFXIXkL6xR+bKFZY= github.com/onflow/flow-nft/lib/go/contracts v1.2.1/go.mod h1:2gpbza+uzs1k7x31hkpBPlggIRkI53Suo0n2AyA2HcE= github.com/onflow/flow-nft/lib/go/templates v1.2.0 h1:JSQyh9rg0RC+D1930BiRXN8lrtMs+ubVMK6aQPon6Yc= diff --git a/tests/go.mod b/tests/go.mod index e760a587d..0aa314d6a 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -8,7 +8,7 @@ require ( github.com/onflow/flow-emulator v1.0.0-preview.23 github.com/onflow/flow-evm-gateway v0.0.0-20240201154855-4d4d3d3f19c7 github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd - github.com/onflow/flow-go-sdk v1.0.0-preview.30 + github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347 github.com/onflow/go-ethereum v1.13.4 github.com/rs/zerolog v1.31.0 github.com/stretchr/testify v1.9.0 diff --git a/tests/go.sum b/tests/go.sum index 276d73ac8..092afb90a 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -2034,6 +2034,7 @@ github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd/go.mod h1:5ysH9w github.com/onflow/flow-go-sdk v1.0.0-M1/go.mod h1:TDW0MNuCs4SvqYRUzkbRnRmHQL1h4X8wURsCw9P9beo= github.com/onflow/flow-go-sdk v1.0.0-preview.30 h1:62IwC7l8Uw1mxoZe7ewJII0HFHLUMsg04z1BW3JSEfM= github.com/onflow/flow-go-sdk v1.0.0-preview.30/go.mod h1:PBIk3vLqU1aLdbWPw7ljRDmwSGLcsuk/ipL9eLMgWwc= +github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347/go.mod h1:J4iKISX976mxV3ReTWiURG/ai50h61s2XJZ3YcK2lCg= github.com/onflow/flow-nft/lib/go/contracts v1.2.1 h1:woAAS5z651sDpi7ihAHll8NvRS9uFXIXkL6xR+bKFZY= github.com/onflow/flow-nft/lib/go/contracts v1.2.1/go.mod h1:2gpbza+uzs1k7x31hkpBPlggIRkI53Suo0n2AyA2HcE= github.com/onflow/flow-nft/lib/go/templates v1.2.0 h1:JSQyh9rg0RC+D1930BiRXN8lrtMs+ubVMK6aQPon6Yc= From 6e4b88a4e06b58fecebff93b4f25b5f3b9ab9941 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 14:43:53 +0200 Subject: [PATCH 05/15] replace to spork clients as collection --- services/requester/cross-spork_client.go | 126 ++++++++++++++--------- 1 file changed, 79 insertions(+), 47 deletions(-) diff --git a/services/requester/cross-spork_client.go b/services/requester/cross-spork_client.go index c200917e9..1fdf3dd76 100644 --- a/services/requester/cross-spork_client.go +++ b/services/requester/cross-spork_client.go @@ -9,6 +9,7 @@ import ( "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/access" "github.com/rs/zerolog" + "golang.org/x/exp/slices" ) var ErrOutOfRange = errors.New("height is out of range for provided spork clients") @@ -24,6 +25,64 @@ func (s *sporkClient) contains(height uint64) bool { return height >= s.firstHeight && height <= s.lastHeight } +type sporkClients []*sporkClient + +// addSpork will add a new spork host defined by the first and last height boundary in that spork. +func (s *sporkClients) add(client access.Client) error { + header, err := client.GetLatestBlockHeader(context.Background(), true) + if err != nil { + return fmt.Errorf("could not get latest height using the spork client: %w", err) + } + + info, err := client.GetNodeVersionInfo(context.Background()) + if err != nil { + return fmt.Errorf("could not get node info using the spork client: %w", err) + } + + *s = append(*s, &sporkClient{ + firstHeight: info.NodeRootBlockHeight, + lastHeight: header.Height, + client: client, + }) + + return nil +} + +// get spork client that contains the height or nil if not found. +func (s *sporkClients) get(height uint64) access.Client { + for _, spork := range *s { + if spork.contains(height) { + return spork.client + } + } + + return nil +} + +// continuous checks if all the past spork clients create a continuous +// range of heights. +func (s *sporkClients) continuous() bool { + firsts := make([]uint64, len(*s)) + lasts := make([]uint64, len(*s)) + + for i, c := range *s { + firsts[i] = c.firstHeight + lasts[i] = c.lastHeight + } + + slices.Sort(firsts) + slices.Sort(lasts) + + // make sure each last height is one smaller than next range first height + for i := 0; i < len(lasts)-1; i++ { + if lasts[i]+1 != firsts[i+1] { + return false + } + } + + return true +} + // CrossSporkClient is a wrapper around the Flow AN client that can // access different AN APIs based on the height boundaries of the sporks. // @@ -34,7 +93,7 @@ func (s *sporkClient) contains(height uint64) bool { // that shadows the original access Client function. type CrossSporkClient struct { logger zerolog.Logger - sporkClients []*sporkClient + sporkClients *sporkClients currentSporkFirstHeight uint64 access.Client } @@ -51,48 +110,23 @@ func NewCrossSporkClient( return nil, err } - client := &CrossSporkClient{ - logger: logger, - sporkClients: make([]*sporkClient, 0), - currentSporkFirstHeight: info.NodeRootBlockHeight, - Client: currentSpork, - } - - for _, sporkClient := range pastSporks { - if err := client.addSpork(sporkClient); err != nil { + clients := &sporkClients{} + for _, c := range pastSporks { + if err := clients.add(c); err != nil { return nil, err } } - return client, nil -} - -// addSpork will add a new spork host defined by the first and last height boundary in that spork. -func (c *CrossSporkClient) addSpork(client access.Client) error { - header, err := client.GetLatestBlockHeader(context.Background(), true) - if err != nil { - return fmt.Errorf("could not get latest height using the spork client: %w", err) - } - - info, err := client.GetNodeVersionInfo(context.Background()) - if err != nil { - return fmt.Errorf("could not get node info using the spork client: %w", err) - } - - spork := &sporkClient{ - firstHeight: info.NodeRootBlockHeight, - lastHeight: header.Height, - client: client, + if !clients.continuous() { + return nil, fmt.Errorf("provided past-spork clients don't create a continuous range of heights") } - c.sporkClients = append(c.sporkClients, spork) - - c.logger.Info(). - Uint64("spork-last-height", header.Height). - Uint64("spork-first-height", info.NodeRootBlockHeight). - Msg("added spork client") - - return nil + return &CrossSporkClient{ + logger: logger, + currentSporkFirstHeight: info.NodeRootBlockHeight, + sporkClients: clients, + Client: currentSpork, + }, nil } // IsPastSpork will check if the provided height is contained in the previous sporks. @@ -111,18 +145,16 @@ func (c *CrossSporkClient) getClientForHeight(height uint64) (access.Client, err return c.Client, nil } - for _, spork := range c.sporkClients { - if spork.contains(height) { - c.logger.Debug(). - Uint64("requested-cadence-height", height). - Msg("using previous spork client") - - return spork.client, nil - } + client := c.sporkClients.get(height) + if client == nil { + return nil, ErrOutOfRange } - // if not found return an error - return nil, ErrOutOfRange + c.logger.Debug(). + Uint64("requested-cadence-height", height). + Msg("using previous spork client") + + return client, nil } // GetLatestHeightForSpork will determine the spork client in which the provided height is contained From bcec322bb4019e96258fdc595127d256b15def32 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 14:52:44 +0200 Subject: [PATCH 06/15] move mock client --- services/ingestion/subscriber_test.go | 74 ++--------------------- services/testutils/mock_client.go | 84 +++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 70 deletions(-) create mode 100644 services/testutils/mock_client.go diff --git a/services/ingestion/subscriber_test.go b/services/ingestion/subscriber_test.go index c55163748..d944bcea3 100644 --- a/services/ingestion/subscriber_test.go +++ b/services/ingestion/subscriber_test.go @@ -8,79 +8,13 @@ import ( "github.com/onflow/flow-evm-gateway/models" "github.com/onflow/flow-evm-gateway/services/requester" + "github.com/onflow/flow-evm-gateway/services/testutils" - "github.com/onflow/flow-go-sdk" - "github.com/onflow/flow-go-sdk/access/mocks" flowGo "github.com/onflow/flow-go/model/flow" - "github.com/onflow/flow-go/storage" "github.com/rs/zerolog" "github.com/stretchr/testify/require" ) -type mockClient struct { - *mocks.Client - getLatestBlockHeaderFunc func(context.Context, bool) (*flow.BlockHeader, error) - getBlockHeaderByHeightFunc func(context.Context, uint64) (*flow.BlockHeader, error) - subscribeEventsByBlockHeightFunc func(context.Context, uint64, flow.EventFilter, ...access.SubscribeOption) (<-chan flow.BlockEvents, <-chan error, error) -} - -func (c *mockClient) GetBlockHeaderByHeight(ctx context.Context, height uint64) (*flow.BlockHeader, error) { - return c.getBlockHeaderByHeightFunc(ctx, height) -} - -func (c *mockClient) GetLatestBlockHeader(ctx context.Context, sealed bool) (*flow.BlockHeader, error) { - return c.getLatestBlockHeaderFunc(ctx, sealed) -} - -func (c *mockClient) SubscribeEventsByBlockHeight( - ctx context.Context, - startHeight uint64, - filter flow.EventFilter, - opts ...access.SubscribeOption, -) (<-chan flow.BlockEvents, <-chan error, error) { - return c.subscribeEventsByBlockHeightFunc(ctx, startHeight, filter, opts...) -} - -func setupClient(startHeight uint64, endHeight uint64) access.Client { - return &mockClient{ - Client: &mocks.Client{}, - getLatestBlockHeaderFunc: func(ctx context.Context, sealed bool) (*flow.BlockHeader, error) { - return &flow.BlockHeader{ - Height: endHeight, - }, nil - }, - getBlockHeaderByHeightFunc: func(ctx context.Context, height uint64) (*flow.BlockHeader, error) { - if height < startHeight || height > endHeight { - return nil, storage.ErrNotFound - } - - return &flow.BlockHeader{ - Height: height, - }, nil - }, - subscribeEventsByBlockHeightFunc: func( - ctx context.Context, - startHeight uint64, - filter flow.EventFilter, - opts ...access.SubscribeOption, - ) (<-chan flow.BlockEvents, <-chan error, error) { - events := make(chan flow.BlockEvents) - - go func() { - defer close(events) - - for i := startHeight; i <= endHeight; i++ { - events <- flow.BlockEvents{ - Height: i, - } - } - }() - - return events, make(chan error), nil - }, - } -} - // this test simulates two previous sporks and current spork // the subscriber should start with spork1Client then proceed to // spork2Client and end with currentClient. @@ -89,10 +23,10 @@ func Test_Subscribing(t *testing.T) { const endHeight = 50 sporkClients := []access.Client{ - setupClient(1, 10), - setupClient(11, 20), + testutils.SetupClientForRange(1, 10), + testutils.SetupClientForRange(11, 20), } - currentClient := setupClient(21, endHeight) + currentClient := testutils.SetupClientForRange(21, endHeight) client, err := requester.NewCrossSporkClient(currentClient, sporkClients, zerolog.Nop()) require.NoError(t, err) diff --git a/services/testutils/mock_client.go b/services/testutils/mock_client.go new file mode 100644 index 000000000..eece1c9df --- /dev/null +++ b/services/testutils/mock_client.go @@ -0,0 +1,84 @@ +package testutils + +import ( + "context" + + "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go-sdk/access" + "github.com/onflow/flow-go-sdk/access/mocks" + "github.com/onflow/flow-go/storage" +) + +type MockClient struct { + *mocks.Client + getLatestBlockHeaderFunc func(context.Context, bool) (*flow.BlockHeader, error) + getBlockHeaderByHeightFunc func(context.Context, uint64) (*flow.BlockHeader, error) + subscribeEventsByBlockHeightFunc func(context.Context, uint64, flow.EventFilter, ...access.SubscribeOption) (<-chan flow.BlockEvents, <-chan error, error) + getNodeVersionInfoFunc func(ctx context.Context) (*flow.NodeVersionInfo, error) +} + +func (c *MockClient) GetBlockHeaderByHeight(ctx context.Context, height uint64) (*flow.BlockHeader, error) { + return c.getBlockHeaderByHeightFunc(ctx, height) +} + +func (c *MockClient) GetLatestBlockHeader(ctx context.Context, sealed bool) (*flow.BlockHeader, error) { + return c.getLatestBlockHeaderFunc(ctx, sealed) +} + +func (c *MockClient) GetNodeVersionInfo(ctx context.Context) (*flow.NodeVersionInfo, error) { + return c.getNodeVersionInfoFunc(ctx) +} + +func (c *MockClient) SubscribeEventsByBlockHeight( + ctx context.Context, + startHeight uint64, + filter flow.EventFilter, + opts ...access.SubscribeOption, +) (<-chan flow.BlockEvents, <-chan error, error) { + return c.subscribeEventsByBlockHeightFunc(ctx, startHeight, filter, opts...) +} + +func SetupClientForRange(startHeight uint64, endHeight uint64) access.Client { + return &MockClient{ + Client: &mocks.Client{}, + getLatestBlockHeaderFunc: func(ctx context.Context, sealed bool) (*flow.BlockHeader, error) { + return &flow.BlockHeader{ + Height: endHeight, + }, nil + }, + getBlockHeaderByHeightFunc: func(ctx context.Context, height uint64) (*flow.BlockHeader, error) { + if height < startHeight || height > endHeight { + return nil, storage.ErrNotFound + } + + return &flow.BlockHeader{ + Height: height, + }, nil + }, + getNodeVersionInfoFunc: func(ctx context.Context) (*flow.NodeVersionInfo, error) { + return &flow.NodeVersionInfo{ + NodeRootBlockHeight: startHeight, + }, nil + }, + subscribeEventsByBlockHeightFunc: func( + ctx context.Context, + startHeight uint64, + filter flow.EventFilter, + opts ...access.SubscribeOption, + ) (<-chan flow.BlockEvents, <-chan error, error) { + events := make(chan flow.BlockEvents) + + go func() { + defer close(events) + + for i := startHeight; i <= endHeight; i++ { + events <- flow.BlockEvents{ + Height: i, + } + } + }() + + return events, make(chan error), nil + }, + } +} From a5810fc8da95f5e6df167b6111a4323d2379cbb0 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 14:56:17 +0200 Subject: [PATCH 07/15] add cross spork client tests --- services/requester/cross-spork_client_test.go | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 services/requester/cross-spork_client_test.go diff --git a/services/requester/cross-spork_client_test.go b/services/requester/cross-spork_client_test.go new file mode 100644 index 000000000..2bc6f7b91 --- /dev/null +++ b/services/requester/cross-spork_client_test.go @@ -0,0 +1,55 @@ +package requester + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/onflow/flow-evm-gateway/services/testutils" +) + +func Test_CrossSporkClient(t *testing.T) { + t.Run("contains", func(t *testing.T) { + first := uint64(10) + last := uint64(100) + client := sporkClient{ + firstHeight: first, + lastHeight: last, + client: nil, + } + + require.True(t, client.contains(first+1)) + require.True(t, client.contains(last-1)) + require.True(t, client.contains(first)) + require.True(t, client.contains(last)) + require.False(t, client.contains(2)) + require.False(t, client.contains(200)) + }) +} + +func Test_CrossSporkClients(t *testing.T) { + t.Run("add and validate", func(t *testing.T) { + clients := &sporkClients{} + + client1 := testutils.SetupClientForRange(10, 100) + client2 := testutils.SetupClientForRange(101, 200) + + err := clients.add(client1) + require.NoError(t, err) + + err = clients.add(client2) + require.NoError(t, err) + + require.True(t, clients.continuous()) + + require.Equal(t, client1, clients.get(10)) + require.Equal(t, client1, clients.get(100)) + require.Equal(t, client1, clients.get(20)) + require.Equal(t, client2, clients.get(120)) + require.Equal(t, client2, clients.get(101)) + require.Equal(t, client2, clients.get(200)) + + require.Equal(t, nil, clients.get(5)) + require.Equal(t, nil, clients.get(300)) + }) +} From 9572c3dd6b4494a4cc874562fd7430f5efb78721 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 14:59:55 +0200 Subject: [PATCH 08/15] add failed test --- services/requester/cross-spork_client_test.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/services/requester/cross-spork_client_test.go b/services/requester/cross-spork_client_test.go index 2bc6f7b91..310631dbc 100644 --- a/services/requester/cross-spork_client_test.go +++ b/services/requester/cross-spork_client_test.go @@ -34,11 +34,8 @@ func Test_CrossSporkClients(t *testing.T) { client1 := testutils.SetupClientForRange(10, 100) client2 := testutils.SetupClientForRange(101, 200) - err := clients.add(client1) - require.NoError(t, err) - - err = clients.add(client2) - require.NoError(t, err) + require.NoError(t, clients.add(client2)) + require.NoError(t, clients.add(client1)) require.True(t, clients.continuous()) @@ -52,4 +49,16 @@ func Test_CrossSporkClients(t *testing.T) { require.Equal(t, nil, clients.get(5)) require.Equal(t, nil, clients.get(300)) }) + + t.Run("add and validate not-continues", func(t *testing.T) { + clients := &sporkClients{} + + client1 := testutils.SetupClientForRange(10, 30) + client2 := testutils.SetupClientForRange(50, 80) + + require.NoError(t, clients.add(client1)) + require.NoError(t, clients.add(client2)) + + require.False(t, clients.continuous()) + }) } From 05d9c5602721c2624e556dfe7b68bb30540a311b Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Thu, 23 May 2024 15:15:06 +0200 Subject: [PATCH 09/15] add client test --- services/requester/cross-spork_client_test.go | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/services/requester/cross-spork_client_test.go b/services/requester/cross-spork_client_test.go index 310631dbc..67743d773 100644 --- a/services/requester/cross-spork_client_test.go +++ b/services/requester/cross-spork_client_test.go @@ -1,8 +1,12 @@ package requester import ( + "context" "testing" + "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go-sdk/access" + "github.com/rs/zerolog" "github.com/stretchr/testify/require" "github.com/onflow/flow-evm-gateway/services/testutils" @@ -62,3 +66,62 @@ func Test_CrossSporkClients(t *testing.T) { require.False(t, clients.continuous()) }) } + +func Test_CrossSpork(t *testing.T) { + t.Run("client", func(t *testing.T) { + past1Last := uint64(300) + past2Last := uint64(500) + currentLast := uint64(1000) + current := testutils.SetupClientForRange(501, currentLast) + past1 := testutils.SetupClientForRange(100, past1Last) + past2 := testutils.SetupClientForRange(301, past2Last) + + client, err := NewCrossSporkClient(current, []access.Client{past2, past1}, zerolog.Nop()) + require.NoError(t, err) + + c, err := client.getClientForHeight(150) + require.NoError(t, err) + require.Equal(t, past1, c) + + c, err = client.getClientForHeight(past2Last - 1) + require.NoError(t, err) + require.Equal(t, past2, c) + + c, err = client.getClientForHeight(600) + require.NoError(t, err) + require.Equal(t, current, c) + + c, err = client.getClientForHeight(10) + require.Nil(t, c) + require.ErrorIs(t, err, ErrOutOfRange) + + require.True(t, client.IsPastSpork(200)) + require.True(t, client.IsPastSpork(past1Last)) + require.False(t, client.IsPastSpork(past2Last+1)) + require.False(t, client.IsPastSpork(600)) + + _, err = client.ExecuteScriptAtBlockHeight(context.Background(), 20, []byte{}, nil) + require.ErrorIs(t, err, ErrOutOfRange) + + _, err = client.GetBlockHeaderByHeight(context.Background(), 20) + require.ErrorIs(t, err, ErrOutOfRange) + + _, _, err = client.SubscribeEventsByBlockHeight(context.Background(), 20, flow.EventFilter{}, nil) + require.ErrorIs(t, err, ErrOutOfRange) + + height, err := client.GetLatestHeightForSpork(context.Background(), past2Last-10) + require.NoError(t, err) + require.Equal(t, past2Last, height) + + height, err = client.GetLatestHeightForSpork(context.Background(), past1Last-10) + require.NoError(t, err) + require.Equal(t, past1Last, height) + + height, err = client.GetLatestHeightForSpork(context.Background(), currentLast-10) + require.NoError(t, err) + require.Equal(t, currentLast, height) + + _, err = client.GetLatestHeightForSpork(context.Background(), 10) + require.ErrorIs(t, err, ErrOutOfRange) + }) +} From 7ff0ac1c2edbee118a860ebbb67dcb3bf62e0e17 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Fri, 24 May 2024 12:12:53 +0200 Subject: [PATCH 10/15] mod tidy --- tests/go.sum | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/go.sum b/tests/go.sum index 092afb90a..cb8ddcd98 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -1018,7 +1018,7 @@ github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZw github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= github.com/aws/aws-sdk-go-v2 v1.23.1/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA= -github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= +github.com/aws/aws-sdk-go-v2 v1.27.0 h1:7bZWKoXhzI+mMR/HjdMx8ZCC5+6fY0lS5tr0bbgiLlo= github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= github.com/aws/aws-sdk-go-v2/config v1.25.5/go.mod h1:Bf4gDvy4ZcFIK0rqDu1wp9wrubNba2DojiPB2rt6nvI= @@ -1040,7 +1040,7 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1x github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4/go.mod h1:aYCGNjyUCUelhofxlZyj63srdxWUSsBSGg5l6MCuXuE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 h1:Wx0rlZoEJR7JwlSZcHnEa7CNjrSIyVxMFWGAaXy4fJY= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.0 h1:HWsM0YQWX76V6MOp07YuTYacm8k7h69ObJuw7Nck+og= github.com/aws/aws-sdk-go-v2/service/kms v1.26.3/go.mod h1:N3++/sLV97B8Zliz7KRqNcojOX7iMBZWKiuit5FKtH0= github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= @@ -2032,8 +2032,7 @@ github.com/onflow/flow-ft/lib/go/templates v1.0.0/go.mod h1:uQ8XFqmMK2jxyBSVrmyu github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd h1:bSoQMARSC4dk6sQPv6SRkV7QvovKoNksTnydK9e5hL4= github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd/go.mod h1:5ysH9wggXlvJqbALEBZc2uNx6DIE+QsBoocuM8bSGC0= github.com/onflow/flow-go-sdk v1.0.0-M1/go.mod h1:TDW0MNuCs4SvqYRUzkbRnRmHQL1h4X8wURsCw9P9beo= -github.com/onflow/flow-go-sdk v1.0.0-preview.30 h1:62IwC7l8Uw1mxoZe7ewJII0HFHLUMsg04z1BW3JSEfM= -github.com/onflow/flow-go-sdk v1.0.0-preview.30/go.mod h1:PBIk3vLqU1aLdbWPw7ljRDmwSGLcsuk/ipL9eLMgWwc= +github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347 h1:qXJa8wp2aJLzDO5TVmMxaSHlrZ0/O/HMHzrpFUDP0eo= github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347/go.mod h1:J4iKISX976mxV3ReTWiURG/ai50h61s2XJZ3YcK2lCg= github.com/onflow/flow-nft/lib/go/contracts v1.2.1 h1:woAAS5z651sDpi7ihAHll8NvRS9uFXIXkL6xR+bKFZY= github.com/onflow/flow-nft/lib/go/contracts v1.2.1/go.mod h1:2gpbza+uzs1k7x31hkpBPlggIRkI53Suo0n2AyA2HcE= From 88bc4edfddfd1b2ff0b356d70fc42263ede1dd9a Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Fri, 24 May 2024 13:21:47 +0200 Subject: [PATCH 11/15] add err message --- services/requester/cross-spork_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/requester/cross-spork_client.go b/services/requester/cross-spork_client.go index 1fdf3dd76..25e4932e8 100644 --- a/services/requester/cross-spork_client.go +++ b/services/requester/cross-spork_client.go @@ -107,7 +107,7 @@ func NewCrossSporkClient( ) (*CrossSporkClient, error) { info, err := currentSpork.GetNodeVersionInfo(context.Background()) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get node version info: %w", err) } clients := &sporkClients{} From c026fae945b9e89836cccb2f5da9058b33bd8aba Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Fri, 24 May 2024 13:31:43 +0200 Subject: [PATCH 12/15] update emulator node version info api added --- tests/go.mod | 2 +- tests/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/go.mod b/tests/go.mod index 0aa314d6a..0cf8079fc 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/goccy/go-json v0.10.2 github.com/onflow/cadence v1.0.0-preview.29 - github.com/onflow/flow-emulator v1.0.0-preview.23 + github.com/onflow/flow-emulator v1.0.0-preview.23.0.20240524112921-431194fd9bc0 github.com/onflow/flow-evm-gateway v0.0.0-20240201154855-4d4d3d3f19c7 github.com/onflow/flow-go v0.35.5-0.20240517202625-55f862b45dfd github.com/onflow/flow-go-sdk v1.0.0-preview.30.0.20240523120036-f9d51677b347 diff --git a/tests/go.sum b/tests/go.sum index cb8ddcd98..fec59d495 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -2023,8 +2023,8 @@ github.com/onflow/flow-core-contracts/lib/go/contracts v1.1.0 h1:AegPBm079X0qjne github.com/onflow/flow-core-contracts/lib/go/contracts v1.1.0/go.mod h1:u/mkP/B+PbV33tEG3qfkhhBlydSvAKxfLZSfB4lsJHg= github.com/onflow/flow-core-contracts/lib/go/templates v1.0.0 h1:za6bxPPW4JIsthhasUDTa1ruKjIO8DIhun9INQfj61Y= github.com/onflow/flow-core-contracts/lib/go/templates v1.0.0/go.mod h1:NgbMOYnMh0GN48VsNKZuiwK7uyk38Wyo8jN9+C9QE30= -github.com/onflow/flow-emulator v1.0.0-preview.23 h1:wgbwhRkzaSZbr348og8csr2AvLrcyGSP8HR8P2mxa3g= -github.com/onflow/flow-emulator v1.0.0-preview.23/go.mod h1:QprPouTWO3iv9VF/y4Ksltv2XIbzNMzjjr5zzq51i7Q= +github.com/onflow/flow-emulator v1.0.0-preview.23.0.20240524112921-431194fd9bc0 h1:kpg8rCXLbxXaxHpw6vbHS88jMDlDpVayQVOUgQmR3Mc= +github.com/onflow/flow-emulator v1.0.0-preview.23.0.20240524112921-431194fd9bc0/go.mod h1:QprPouTWO3iv9VF/y4Ksltv2XIbzNMzjjr5zzq51i7Q= github.com/onflow/flow-ft/lib/go/contracts v1.0.0 h1:mToacZ5NWqtlWwk/7RgIl/jeKB/Sy/tIXdw90yKHcV0= github.com/onflow/flow-ft/lib/go/contracts v1.0.0/go.mod h1:PwsL8fC81cjnUnTfmyL/HOIyHnyaw/JA474Wfj2tl6A= github.com/onflow/flow-ft/lib/go/templates v1.0.0 h1:6cMS/lUJJ17HjKBfMO/eh0GGvnpElPgBXx7h5aoWJhs= From 350338269f7d8dd436d3637ed44692a7cf9e4afc Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Fri, 24 May 2024 13:34:39 +0200 Subject: [PATCH 13/15] force close ws connections --- tests/web3js/eth_logs_filtering_test.js | 4 +++- tests/web3js/eth_streaming_filters_test.js | 2 ++ tests/web3js/eth_streaming_test.js | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/web3js/eth_logs_filtering_test.js b/tests/web3js/eth_logs_filtering_test.js index 216ee0e29..f48602ae2 100644 --- a/tests/web3js/eth_logs_filtering_test.js +++ b/tests/web3js/eth_logs_filtering_test.js @@ -4,6 +4,8 @@ const helpers = require('./helpers') const web3 = conf.web3 it('emit logs and retrieve them using different filters', async() => { + setTimeout(() => process.exit(1), 19*1000) // hack if the ws connection is not closed + let deployed = await helpers.deployContract("storage") let contractAddress = deployed.receipt.contractAddress @@ -88,4 +90,4 @@ it('emit logs and retrieve them using different filters', async() => { // todo compose more complex topic filters using OR and AND logic */ -}).timeout(10*1000) \ No newline at end of file +}).timeout(20*1000) \ No newline at end of file diff --git a/tests/web3js/eth_streaming_filters_test.js b/tests/web3js/eth_streaming_filters_test.js index 38cdbc4af..b9cdcfe54 100644 --- a/tests/web3js/eth_streaming_filters_test.js +++ b/tests/web3js/eth_streaming_filters_test.js @@ -65,6 +65,8 @@ async function assertFilterLogs(subscription, expectedLogs) { } it('streaming of logs using filters', async() => { + setTimeout(() => process.exit(1), (timeout-1)*1000) // hack if the ws connection is not closed + let contractDeployment = await helpers.deployContract("storage") let contractAddress = contractDeployment.receipt.contractAddress diff --git a/tests/web3js/eth_streaming_test.js b/tests/web3js/eth_streaming_test.js index 6c3d94ece..f0595ea03 100644 --- a/tests/web3js/eth_streaming_test.js +++ b/tests/web3js/eth_streaming_test.js @@ -6,6 +6,8 @@ const {Web3} = require("web3"); const timeout = 30 // test timeout seconds it('streaming of logs using filters', async() => { + setTimeout(() => process.exit(1), (timeout-1)*1000) // hack if the ws connection is not closed + let deployed = await helpers.deployContract("storage") let contractAddress = deployed.receipt.contractAddress From 2e7dea44e36795036b5226d834463313bdfb3504 Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Fri, 24 May 2024 13:36:22 +0200 Subject: [PATCH 14/15] remove getting transaction status --- services/requester/requester.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/services/requester/requester.go b/services/requester/requester.go index 8c3c589f5..e88bb45a4 100644 --- a/services/requester/requester.go +++ b/services/requester/requester.go @@ -232,23 +232,6 @@ func (e *EVM) signAndSend(ctx context.Context, script []byte, args ...cadence.Va return flow.EmptyID, fmt.Errorf("failed to send transaction: %w", err) } - go func(id flow.Identifier) { - res, _ := e.client.GetTransactionResult(context.Background(), id) - if res != nil && res.Error != nil { - e.logger.Error(). - Str("flow-id", id.String()). - Err(res.Error). - Msg("flow transaction failed to execute") - return - } - - e.logger.Info(). - Str("flow-id", id.String()). - Str("events", fmt.Sprintf("%v", res.Events)). - Str("status", res.Status.String()). - Msg("flow transaction executed successfully") - }(flowTx.ID()) - return flowTx.ID(), nil } From 05245f21e1ea7c3dbcbaa95f266281cb7eced3fc Mon Sep 17 00:00:00 2001 From: sideninja <75445744+sideninja@users.noreply.github.com> Date: Fri, 24 May 2024 13:55:27 +0200 Subject: [PATCH 15/15] sort clients on add --- services/requester/cross-spork_client.go | 21 +++++++------------ services/requester/cross-spork_client_test.go | 4 +++- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/services/requester/cross-spork_client.go b/services/requester/cross-spork_client.go index 25e4932e8..92f42f6c0 100644 --- a/services/requester/cross-spork_client.go +++ b/services/requester/cross-spork_client.go @@ -45,6 +45,11 @@ func (s *sporkClients) add(client access.Client) error { client: client, }) + // make sure clients are always sorted + slices.SortFunc(*s, func(a, b *sporkClient) int { + return int(a.firstHeight) - int(b.firstHeight) + }) + return nil } @@ -62,20 +67,8 @@ func (s *sporkClients) get(height uint64) access.Client { // continuous checks if all the past spork clients create a continuous // range of heights. func (s *sporkClients) continuous() bool { - firsts := make([]uint64, len(*s)) - lasts := make([]uint64, len(*s)) - - for i, c := range *s { - firsts[i] = c.firstHeight - lasts[i] = c.lastHeight - } - - slices.Sort(firsts) - slices.Sort(lasts) - - // make sure each last height is one smaller than next range first height - for i := 0; i < len(lasts)-1; i++ { - if lasts[i]+1 != firsts[i+1] { + for i := 0; i < len(*s)-1; i++ { + if (*s)[i].lastHeight+1 != (*s)[i+1].firstHeight { return false } } diff --git a/services/requester/cross-spork_client_test.go b/services/requester/cross-spork_client_test.go index 67743d773..51e8c70c9 100644 --- a/services/requester/cross-spork_client_test.go +++ b/services/requester/cross-spork_client_test.go @@ -37,8 +37,10 @@ func Test_CrossSporkClients(t *testing.T) { client1 := testutils.SetupClientForRange(10, 100) client2 := testutils.SetupClientForRange(101, 200) + client3 := testutils.SetupClientForRange(201, 300) require.NoError(t, clients.add(client2)) + require.NoError(t, clients.add(client3)) require.NoError(t, clients.add(client1)) require.True(t, clients.continuous()) @@ -51,7 +53,7 @@ func Test_CrossSporkClients(t *testing.T) { require.Equal(t, client2, clients.get(200)) require.Equal(t, nil, clients.get(5)) - require.Equal(t, nil, clients.get(300)) + require.Equal(t, nil, clients.get(310)) }) t.Run("add and validate not-continues", func(t *testing.T) {