Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add tx confirm func and create virtual group retry #981

Merged
merged 2 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion base/gfspapp/sign_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func (g *GfSpBaseApp) GfSpSign(ctx context.Context, req *gfspserver.GfSpSignRequ
metrics.ReqTime.WithLabelValues(SignerSuccessReplicateApproval).Observe(time.Since(startTime).Seconds())
}
case *gfspserver.GfSpSignRequest_CreateGlobalVirtualGroup:
err = g.signer.CreateGlobalVirtualGroup(ctx, &virtualgrouptypes.MsgCreateGlobalVirtualGroup{
txHash, err = g.signer.CreateGlobalVirtualGroup(ctx, &virtualgrouptypes.MsgCreateGlobalVirtualGroup{
StorageProvider: g.operatorAddress,
FamilyId: t.CreateGlobalVirtualGroup.GetVirtualGroupFamilyId(),
SecondarySpIds: t.CreateGlobalVirtualGroup.GetSecondarySpIds(),
Expand Down
75 changes: 75 additions & 0 deletions base/gnfd/gnfd_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package gnfd

import (
"context"
"fmt"
"math"
"strconv"
"strings"
"time"

sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"

"github.com/bnb-chain/greenfield-storage-provider/pkg/metrics"
"github.com/cosmos/cosmos-sdk/types/query"
Expand Down Expand Up @@ -87,6 +91,11 @@ const (
ChainSuccessVerifyPutObjectPermission = "verify_putt_object_permission_success"
// ChainFailureVerifyPutObjectPermission defines the metrics label of unsuccessfully verify put object permission
ChainFailureVerifyPutObjectPermission = "verify_put_object_permission_failure"

// ConfirmBlockNumber defines wait block number.
ConfirmBlockNumber = 3
// WaitForNextBlockTimeout define wait block timeout.
WaitForNextBlockTimeout = 30 * time.Second
)

// CurrentHeight the block height sub one as the stable height.
Expand Down Expand Up @@ -783,3 +792,69 @@ func (g *Gnfd) VerifyPutObjectPermission(ctx context.Context, account, bucket, o
}
return false, err
}

// ConfirmTransaction is used to confirm whether the transaction is on the chain.
func (g *Gnfd) ConfirmTransaction(ctx context.Context, txHash string) (*sdk.TxResponse, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should have a timeout for retry.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, only retry once and there is a timeout in waitForNextBlock.

Copy link
Collaborator

@fynnss fynnss Aug 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only retry once? The transaction may be completed after several blocks

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retrying once basically guarantees whether it is in the current block or the next block.
what is the suggestion here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least 3 blocks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

startTime := time.Now()
defer metrics.GnfdChainTime.WithLabelValues("confirm_transaction").Observe(time.Since(startTime).Seconds())
client := g.getCurrentClient().GnfdClient()
for i := 0; i < ConfirmBlockNumber; i++ {
txResponse, err := client.GetTx(ctx, &tx.GetTxRequest{Hash: txHash})
if err != nil {
if strings.Contains(err.Error(), "not found") {
// Tx not found, wait for next block and try again
if err = g.WaitForNextBlock(ctx); err != nil {
return nil, err
}
continue
}
return nil, err
}
// Tx found
return txResponse.TxResponse, nil
}
return nil, fmt.Errorf("failed to confirm transaction, tx_hash=%s", txHash)
}

// WaitForNextBlock is used to chain generate a new block.
func (g *Gnfd) WaitForNextBlock(ctx context.Context) error {
startTime := time.Now()
defer metrics.GnfdChainTime.WithLabelValues("wait_for_next_block").Observe(time.Since(startTime).Seconds())
var (
err error
height int64
latestBlockHeight int64
)
height, err = g.getLatestBlockHeight(ctx)
if err != nil {
return err
}
ctxTimeout, cancel := context.WithTimeout(ctx, WaitForNextBlockTimeout)
defer cancel()

ticker := time.NewTicker(time.Second)
defer ticker.Stop()

for {
if latestBlockHeight, err = g.getLatestBlockHeight(ctx); err != nil {
return err
}
if latestBlockHeight >= height+1 {
return nil
}
select {
case <-ctxTimeout.Done():
return fmt.Errorf("timeout exceeded waiting for block")
case <-ticker.C:
}
}
}

func (g *Gnfd) getLatestBlockHeight(ctx context.Context) (int64, error) {
client := g.getCurrentClient().GnfdClient()
block, err := client.GetLatestBlock(ctx, &tmservice.GetLatestBlockRequest{})
if err != nil {
return 0, err
}
return block.SdkBlock.Header.Height, nil
}
21 changes: 17 additions & 4 deletions core/consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package consensus
import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

paymenttypes "github.com/bnb-chain/greenfield/x/payment/types"
Expand Down Expand Up @@ -66,6 +67,10 @@ type Consensus interface {
ListenObjectSeal(ctx context.Context, objectID uint64, timeOutHeight int) (bool, error)
// ListenRejectUnSealObject returns an indication of the object is rejected.
ListenRejectUnSealObject(ctx context.Context, objectID uint64, timeoutHeight int) (bool, error)
// ConfirmTransaction is used to confirm whether the transaction is on the chain.
ConfirmTransaction(ctx context.Context, txHash string) (*sdk.TxResponse, error)
// WaitForNextBlock is used to chain generate a new block.
WaitForNextBlock(ctx context.Context) error
// Close the Consensus interface.
Close() error
}
Expand All @@ -90,7 +95,7 @@ func (*NullConsensus) QuerySPFreeQuota(context.Context, string) (uint64, error)
return 0, nil
}

func (*NullConsensus) QuerySPPrice(ctx context.Context, operatorAddress string) (sptypes.SpStoragePrice, error) {
func (*NullConsensus) QuerySPPrice(context.Context, string) (sptypes.SpStoragePrice, error) {
return sptypes.SpStoragePrice{}, nil
}

Expand All @@ -110,15 +115,15 @@ func (*NullConsensus) ListGlobalVirtualGroupsByFamilyID(context.Context, uint32)
return nil, nil
}

func (*NullConsensus) QueryVirtualGroupFamily(ctx context.Context, vgfID uint32) (*virtualgrouptypes.GlobalVirtualGroupFamily, error) {
func (*NullConsensus) QueryVirtualGroupFamily(context.Context, uint32) (*virtualgrouptypes.GlobalVirtualGroupFamily, error) {
return nil, nil
}

func (*NullConsensus) QueryGlobalVirtualGroup(ctx context.Context, gvgID uint32) (*virtualgrouptypes.GlobalVirtualGroup, error) {
func (*NullConsensus) QueryGlobalVirtualGroup(context.Context, uint32) (*virtualgrouptypes.GlobalVirtualGroup, error) {
return nil, nil
}

func (*NullConsensus) QueryVirtualGroupParams(ctx context.Context) (*virtualgrouptypes.Params, error) {
func (*NullConsensus) QueryVirtualGroupParams(context.Context) (*virtualgrouptypes.Params, error) {
return nil, nil
}

Expand Down Expand Up @@ -158,4 +163,12 @@ func (*NullConsensus) ListenObjectSeal(context.Context, uint64, int) (bool, erro
func (*NullConsensus) ListenRejectUnSealObject(context.Context, uint64, int) (bool, error) {
return false, nil
}
func (*NullConsensus) ConfirmTransaction(context.Context, string) (*sdk.TxResponse, error) {
return nil, nil
}

func (*NullConsensus) WaitForNextBlock(context.Context) error {
return nil
}

func (*NullConsensus) Close() error { return nil }
36 changes: 33 additions & 3 deletions core/consensus/consensus_mock.go

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

2 changes: 1 addition & 1 deletion core/module/modular.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ type Signer interface {
// DiscontinueBucket signs the MsgDiscontinueBucket and broadcast the tx to greenfield.
DiscontinueBucket(ctx context.Context, bucket *storagetypes.MsgDiscontinueBucket) (string, error)
// CreateGlobalVirtualGroup signs the MsgCreateGlobalVirtualGroup and broadcast the tx to greenfield.
CreateGlobalVirtualGroup(ctx context.Context, gvg *virtualgrouptypes.MsgCreateGlobalVirtualGroup) error
CreateGlobalVirtualGroup(ctx context.Context, gvg *virtualgrouptypes.MsgCreateGlobalVirtualGroup) (string, error)
// SignMigratePiece signs the GfSpMigratePieceTask for migrating piece
SignMigratePiece(ctx context.Context, task *gfsptask.GfSpMigratePieceTask) ([]byte, error)
// CompleteMigrateBucket signs the MsgCompleteMigrateBucket and broadcast the tx to greenfield.
Expand Down
4 changes: 2 additions & 2 deletions core/module/null_modular.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ func (*NilModular) RejectUnSealObject(context.Context, *storagetypes.MsgRejectSe
func (*NilModular) DiscontinueBucket(context.Context, *storagetypes.MsgDiscontinueBucket) (string, error) {
return "", nil
}
func (*NilModular) CreateGlobalVirtualGroup(context.Context, *virtualgrouptypes.MsgCreateGlobalVirtualGroup) error {
return ErrNilModular
func (*NilModular) CreateGlobalVirtualGroup(context.Context, *virtualgrouptypes.MsgCreateGlobalVirtualGroup) (string, error) {
return "", ErrNilModular
}
func (*NilModular) SignMigratePiece(ctx context.Context, task *gfsptask.GfSpMigratePieceTask) ([]byte, error) {
return nil, ErrNilModular
Expand Down
24 changes: 12 additions & 12 deletions core/spdb/spdb_mock.go

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

Loading
Loading