Skip to content

Commit

Permalink
[NONEVM-984][solana] - Reorg Detection + lighter rpc call (#951)
Browse files Browse the repository at this point in the history
* refactor so txm owns blockhash assignment

* lastValidBlockHeight shouldn't be exported

* better comment

* refactor sendWithRetry to make it clearer

* confirm loop refactor

* fix infinite loop

* move accountID inside msg

* lint fix

* base58 does not contain lower l

* fix hash errors

* fix generate random hash

* remove blockhash as we only need block height

* expired tx changes without tests

* add maybe to mocks

* expiration tests

* send txes through queue

* revert pendingtx leakage of information. overwrite blockhash

* fix order of confirm loop and not found signature check

* fix mocks

* prevent confirmation loop to mark tx as errored when it needs to be rebroadcasted

* fix test

* fix pointer

* add comments

* reduce rpc calls + refactors

* tests + check to save rpc calls

* address feedback + remove redundant impl

* iface comment

* address feedback on compute unit limit and lastValidBlockHeight assignment

* blockhash assignment inside txm.sendWithRetry

* address feedback

* Merge branch 'develop' into nonevm-706-support-custom-bumping-strategy-rpc-expiration-within-confirmation

* refactors after merge

* fix interactive rebase

* fix whitespace diffs

* fix import

* fix mocks

* add on prebroadcaste error

* remove rebroadcast count and fix package

* improve docs

* track status on each signature to detect reorgs

* move things arround + add reorg detection

* linting errors

* fix some state tracking instances

* remove redundant sig update

* move state from txes to sigs

* fix listAllExpiredBroadcastedTxs

* handle reorg after confirm cycle

* associate sigs to retry ctx

* remove unused ctx

* add errored state and remove finalized

* comment

* Revert "comment"

This reverts commit 6bc0c62.

* Revert "remove unused ctx"

This reverts commit 2902ec0.

* Revert "associate sigs to retry ctx"

This reverts commit 8c18891.

* Revert "fix listAllExpiredBroadcastedTxs"

This reverts commit f4c6069.

* Revert "move state from txes to sigs"

This reverts commit 3a6e643.

* fix tx state

* address feedback

* fix ci

* fix lint

* handle multiple sigs case

* improve comment

* improve logic and comments

* fix comparison against blockHeight instead of slotHeight

* address feedback

* fix lint

* fix log

* address feedback

* remove useless slot height

* address feedback

* add comment

* tests and fix some bugs

* address feedback

* address feedback

* validate that tx doesn't exist in any of maps when adding new tx

* get height instead of whole block optimization

* fix mocks on expiration

* fix test

* rebroadcast with new blockhash + add integration tests

* fix integration tests

* remove unused params and better comments

* handle reorg equally for processed and confirmed at a sig level

* add comments and rename txHasReorg to IsTxReorged for better readability

* change test name to solve github CI failing check

* fix ci

* fix tests removing parallel

* fix integration tests

* capture range var

* address feedback

* address feedback
  • Loading branch information
Farber98 authored Jan 10, 2025
1 parent bd667eb commit e2a9566
Show file tree
Hide file tree
Showing 10 changed files with 1,143 additions and 292 deletions.
15 changes: 15 additions & 0 deletions pkg/solana/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type Reader interface {
ChainID(ctx context.Context) (mn.StringID, error)
GetFeeForMessage(ctx context.Context, msg string) (uint64, error)
GetLatestBlock(ctx context.Context) (*rpc.GetBlockResult, error)
// GetLatestBlockHeight returns the latest block height of the node based on the configured commitment type
GetLatestBlockHeight(ctx context.Context) (uint64, error)
GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error)
GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (rpc.BlocksResult, error)
GetBlocksWithLimit(ctx context.Context, startSlot uint64, limit uint64) (*rpc.BlocksResult, error)
Expand Down Expand Up @@ -331,6 +333,19 @@ func (c *Client) GetLatestBlock(ctx context.Context) (*rpc.GetBlockResult, error
return v.(*rpc.GetBlockResult), err
}

// GetLatestBlockHeight returns the latest block height of the node based on the configured commitment type
func (c *Client) GetLatestBlockHeight(ctx context.Context) (uint64, error) {
done := c.latency("latest_block_height")
defer done()
ctx, cancel := context.WithTimeout(ctx, c.txTimeout)
defer cancel()

v, err, _ := c.requestGroup.Do("GetBlockHeight", func() (interface{}, error) {
return c.rpc.GetBlockHeight(ctx, c.commitment)
})
return v.(uint64), err
}

func (c *Client) GetBlock(ctx context.Context, slot uint64) (*rpc.GetBlockResult, error) {
// get block based on slot
done := c.latency("get_block")
Expand Down
32 changes: 32 additions & 0 deletions pkg/solana/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ func TestClient_Reader_Integration(t *testing.T) {
assert.GreaterOrEqual(t, slot, startSlot)
assert.LessOrEqual(t, slot, slot0)
}

// GetLatestBlockHeight
// Test fetching the latest block height
blockHeight, err := c.GetLatestBlockHeight(ctx)
require.NoError(t, err)
require.Greater(t, blockHeight, uint64(0), "Block height should be greater than 0")
}

func TestClient_Reader_ChainID(t *testing.T) {
Expand Down Expand Up @@ -288,6 +294,32 @@ func TestClient_GetBlocks(t *testing.T) {
requestTimeout, 500*time.Millisecond)
}

func TestClient_GetLatestBlockHeight(t *testing.T) {
t.Parallel()

ctx := tests.Context(t)
url := SetupLocalSolNode(t)
requestTimeout := 5 * time.Second
lggr := logger.Test(t)
cfg := config.NewDefault()

// Initialize the client
c, err := NewClient(url, cfg, requestTimeout, lggr)
require.NoError(t, err)

// Get the latest block height
blockHeight, err := c.GetLatestBlockHeight(ctx)
require.NoError(t, err)
require.Greater(t, blockHeight, uint64(0), "Block height should be greater than 0")

// Wait until the block height increases
require.Eventually(t, func() bool {
newBlockHeight, err := c.GetLatestBlockHeight(ctx)
require.NoError(t, err)
return newBlockHeight > blockHeight
}, 10*time.Second, 1*time.Second, "Block height should eventually increase")
}

func TestClient_SendTxDuplicates_Integration(t *testing.T) {
ctx := tests.Context(t)
// set up environment
Expand Down
56 changes: 56 additions & 0 deletions pkg/solana/client/mocks/reader_writer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/solana/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var defaultConfigSet = Chain{
MaxRetries: ptr(int64(0)), // max number of retries (default = 0). when config.MaxRetries < 0), interpreted as MaxRetries = nil and rpc node will do a reasonable number of retries

// fee estimator
FeeEstimatorMode: ptr("fixed"),
FeeEstimatorMode: ptr("fixed"), // "fixed" or "blockhistory"
ComputeUnitPriceMax: ptr(uint64(1_000)),
ComputeUnitPriceMin: ptr(uint64(0)),
ComputeUnitPriceDefault: ptr(uint64(0)),
Expand Down
Loading

0 comments on commit e2a9566

Please sign in to comment.