Skip to content

Commit

Permalink
fix(go/client): gas calculation for tx broadcast (#124)
Browse files Browse the repository at this point in the history
derive parent tx factory to preserve parameters send via cli

Signed-off-by: Artur Troian <[email protected]>
  • Loading branch information
troian authored Feb 29, 2024
1 parent 3d15fce commit 618fece
Showing 1 changed file with 76 additions and 36 deletions.
112 changes: 76 additions & 36 deletions go/node/client/v1beta2/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ import (
)

var (
ErrNotRunning = errors.New("tx client: not running")
ErrSyncTimedOut = errors.New("tx client: timed-out waiting for sequence sync")
ErrNodeCatchingUp = errors.New("tx client: cannot sync from catching up node")
ErrAdjustGas = errors.New("tx client: couldn't adjust gas")
ErrOffline = errors.New("tx client: cannot broadcast in offline mode")
ErrNotRunning = errors.New("tx client: not running")
ErrSyncTimedOut = errors.New("tx client: timed-out waiting for sequence sync")
ErrNodeCatchingUp = errors.New("tx client: cannot sync from catching up node")
ErrAdjustGas = errors.New("tx client: couldn't adjust gas")
ErrSimulateOffline = errors.New("tx client: cannot simulate tx in offline mode")
ErrBroadcastOffline = errors.New("tx client: cannot broadcast tx in offline mode")
)

const (
Expand Down Expand Up @@ -118,13 +119,11 @@ func newSerialTx(ctx context.Context, cctx sdkclient.Context, flags *pflag.FlagS
}

// populate account number, current sequence number
poptxf, err := PrepareFactory(cctx, txf)
txf, err = PrepareFactory(cctx, txf)
if err != nil {
return nil, err
}

poptxf = poptxf.WithSimulateAndExecute(true)

client := &serialBroadcaster{
ctx: ctx,
cctx: cctx,
Expand All @@ -140,7 +139,7 @@ func newSerialTx(ctx context.Context, cctx sdkclient.Context, flags *pflag.FlagS

go client.lc.WatchContext(ctx)
go client.run()
go client.broadcaster(poptxf)
go client.broadcaster(txf)

if !client.cctx.Offline {
go client.sequenceSync()
Expand Down Expand Up @@ -234,20 +233,20 @@ loop:
}
}

func (c *serialBroadcaster) broadcaster(txf tx.Factory) {
syncSequence := func(rErr error) bool {
func (c *serialBroadcaster) broadcaster(ptxf tx.Factory) {
syncSequence := func(f tx.Factory, rErr error) (uint64, bool) {
if rErr != nil {
if sdkerrors.ErrWrongSequence.Is(rErr) {
// attempt to sync account sequence
if rSeq, err := c.syncAccountSequence(txf.Sequence()); err == nil {
txf = txf.WithSequence(rSeq + 1)
if rSeq, err := c.syncAccountSequence(f.Sequence()); err == nil {
return rSeq + 1, true
}

return true
return f.Sequence(), true
}
}

return false
return f.Sequence(), false
}

for {
Expand All @@ -258,12 +257,19 @@ func (c *serialBroadcaster) broadcaster(txf tx.Factory) {
var err error
var resp interface{}

resp, txf, err = AdjustGas(c.cctx, txf, req.msgs...)
if err == nil && !c.cctx.Simulate {
if c.cctx.GenerateOnly {
resp, err = c.generateTxs(ptxf, req.msgs...)
} else {
done:
for i := 0; i < 2; i++ {
resp, txf, err = c.broadcastTxs(txf, req.msgs...)
if !syncSequence(err) {
var rseq uint64
resp, rseq, err = c.broadcastTxs(ptxf, req.msgs...)
ptxf = ptxf.WithSequence(rseq)

rSeq, synced := syncSequence(ptxf, err)
ptxf = ptxf.WithSequence(rSeq)

if !synced {
break done
}
}
Expand All @@ -275,8 +281,9 @@ func (c *serialBroadcaster) broadcaster(txf tx.Factory) {
}

terr := &sdkerrors.Error{}
if errors.Is(err, terr) {
_ = syncSequence(err)
if !c.cctx.GenerateOnly && errors.Is(err, terr) {
rSeq, _ := syncSequence(ptxf, err)
ptxf = ptxf.WithSequence(rSeq)
}

select {
Expand Down Expand Up @@ -326,51 +333,84 @@ func (c *serialBroadcaster) sequenceSync() {
}
}

func (c *serialBroadcaster) broadcastTxs(txf tx.Factory, msgs ...sdk.Msg) (interface{}, tx.Factory, error) {
var err error
func (c *serialBroadcaster) generateTxs(txf tx.Factory, msgs ...sdk.Msg) ([]byte, error) {
if txf.SimulateAndExecute() {
if c.cctx.Offline {
return nil, ErrSimulateOffline
}

txn, err := tx.BuildUnsignedTx(txf, msgs...)
_, adjusted, err := tx.CalculateGas(c.cctx, txf, msgs...)
if err != nil {
return nil, err
}

txf = txf.WithGas(adjusted)
}

utx, err := tx.BuildUnsignedTx(txf, msgs...)
if err != nil {
return nil, txf, err
return nil, err
}

txn.SetFeeGranter(c.cctx.GetFeeGranterAddress())
data, err := c.cctx.TxConfig.TxJSONEncoder()(utx.GetTx())
if err != nil {
return nil, err
}

return data, nil
}

if c.cctx.GenerateOnly {
bytes, err := c.cctx.TxConfig.TxJSONEncoder()(txn.GetTx())
func (c *serialBroadcaster) broadcastTxs(txf tx.Factory, msgs ...sdk.Msg) (interface{}, uint64, error) {
var err error
var resp proto.Message

if txf.SimulateAndExecute() || c.cctx.Simulate {
var adjusted uint64
resp, adjusted, err = tx.CalculateGas(c.cctx, txf, msgs...)
if err != nil {
return nil, txf, err
return nil, txf.Sequence(), err
}

return bytes, txf, nil
txf = txf.WithGas(adjusted)
}

if c.cctx.Simulate {
return resp, txf.Sequence(), nil
}

txn, err := tx.BuildUnsignedTx(txf, msgs...)
if err != nil {
return nil, txf.Sequence(), err
}

if c.cctx.Offline {
return nil, txf, ErrOffline
return nil, txf.Sequence(), ErrBroadcastOffline
}

txn.SetFeeGranter(c.cctx.GetFeeGranterAddress())

err = tx.Sign(txf, c.info.GetName(), txn, true)
if err != nil {
return nil, txf, err
return nil, txf.Sequence(), err
}

bytes, err := c.cctx.TxConfig.TxEncoder()(txn.GetTx())
if err != nil {
return nil, txf, err
return nil, txf.Sequence(), err
}

response, err := c.doBroadcast(c.cctx, bytes, c.broadcastTimeout)
if err != nil {
return response, txf, err
return response, txf.Sequence(), err
}

if response.Code != 0 {
return response, txf, sdkerrors.ABCIError(response.Codespace, response.Code, response.RawLog)
return response, txf.Sequence(), sdkerrors.ABCIError(response.Codespace, response.Code, response.RawLog)
}

txf = txf.WithSequence(txf.Sequence() + 1)

return response, txf, nil
return response, txf.Sequence(), nil
}

func (c *serialBroadcaster) syncAccountSequence(lSeq uint64) (uint64, error) {
Expand Down

0 comments on commit 618fece

Please sign in to comment.