diff --git a/go/oasis-node/cmd/debug/txsource/workload/delegation.go b/go/oasis-node/cmd/debug/txsource/workload/delegation.go index e49f5b18a8e..324df38fe6c 100644 --- a/go/oasis-node/cmd/debug/txsource/workload/delegation.go +++ b/go/oasis-node/cmd/debug/txsource/workload/delegation.go @@ -80,42 +80,14 @@ func (d *delegation) doEscrowTx(ctx context.Context, rng *rand.Rand, cnsc consen tx := staking.NewAddEscrowTx(d.accounts[selectedIdx].reckonedNonce, &transaction.Fee{}, escrow) d.accounts[selectedIdx].reckonedNonce++ - - // Estimate gas. - gas, err := cnsc.EstimateGas(ctx, &consensus.EstimateGasRequest{ - Caller: d.accounts[selectedIdx].signer.Public(), - Transaction: tx, - }) - if err != nil { - return fmt.Errorf("failed to estimate gas: %w", err) - } - tx.Fee.Gas = gas - feeAmount := int64(gas) * gasPrice - if err = tx.Fee.Amount.FromInt64(feeAmount); err != nil { - return fmt.Errorf("fee amount from int64: %w", err) - } - - // Fund account to cover Escrow fees. // We only do one escrow per account at a time, so `delegateAmount` // funds (that are Escrowed) should already be in the balance. - fundAmount := int64(gas) * gasPrice // transaction costs - if err = transferFunds(ctx, d.logger, cnsc, d.fundingAccount, d.accounts[selectedIdx].signer.Public(), fundAmount); err != nil { - return fmt.Errorf("account funding failure: %w", err) - } - - // Sign transaction. - signedTx, err := transaction.Sign(d.accounts[selectedIdx].signer, tx) - if err != nil { - return fmt.Errorf("transaction.Sign: %w", err) - } - d.logger.Debug("submitting escrow transaction", - "from", d.accounts[selectedIdx].signer.Public(), - "to", d.accounts[selectedIdx].delegatedTo, - ) - - // Submit transaction. - if err = cnsc.SubmitTx(ctx, signedTx); err != nil { - return fmt.Errorf("cnsc.SubmitTx: %w", err) + if err := fundSignAndSubmitTx(ctx, d.logger, cnsc, d.accounts[selectedIdx].signer, tx, d.fundingAccount); err != nil { + d.logger.Error("failed to sign and submit escrow transaction", + "tx", tx, + "signer", d.accounts[selectedIdx].signer, + ) + return fmt.Errorf("failed to sign and submit tx: %w", err) } return nil @@ -166,40 +138,12 @@ func (d *delegation) doReclaimEscrowTx(ctx context.Context, rng *rand.Rand, cnsc } tx := staking.NewReclaimEscrowTx(d.accounts[selectedIdx].reckonedNonce, &transaction.Fee{}, reclaim) d.accounts[selectedIdx].reckonedNonce++ - - // Estimate gas. - gas, err := cnsc.EstimateGas(ctx, &consensus.EstimateGasRequest{ - Caller: d.accounts[selectedIdx].signer.Public(), - Transaction: tx, - }) - if err != nil { - return fmt.Errorf("failed to estimate gas: %w", err) - } - tx.Fee.Gas = gas - feeAmount := int64(gas) * gasPrice - if err = tx.Fee.Amount.FromInt64(feeAmount); err != nil { - return fmt.Errorf("fee amount from int64: %w", err) - } - - // Fund account to cover reclaim escrow fees. - fundAmount := int64(gas) * gasPrice // transaction costs - if err = transferFunds(ctx, d.logger, cnsc, d.fundingAccount, d.accounts[selectedIdx].signer.Public(), fundAmount); err != nil { - return fmt.Errorf("account funding failure: %w", err) - } - - signedTx, err := transaction.Sign(d.accounts[selectedIdx].signer, tx) - if err != nil { - return fmt.Errorf("transaction.Sign: %w", err) - } - - d.logger.Debug("submitting reclaim escrow transaction", - "reclaim_from", d.accounts[selectedIdx].delegatedTo, - "account", d.accounts[selectedIdx].signer.Public(), - ) - - // Submit transaction. - if err = cnsc.SubmitTx(ctx, signedTx); err != nil { - return fmt.Errorf("cnsc.SubmitTx: %w", err) + if err = fundSignAndSubmitTx(ctx, d.logger, cnsc, d.accounts[selectedIdx].signer, tx, d.fundingAccount); err != nil { + d.logger.Error("failed to sign and submit reclaim escrow transaction", + "tx", tx, + "signer", d.accounts[selectedIdx].signer, + ) + return fmt.Errorf("failed to sign and submit tx: %w", err) } // Query debonding end epoch for the account. diff --git a/go/oasis-node/cmd/debug/txsource/workload/registration.go b/go/oasis-node/cmd/debug/txsource/workload/registration.go index 4781b96ad23..1596121ca30 100644 --- a/go/oasis-node/cmd/debug/txsource/workload/registration.go +++ b/go/oasis-node/cmd/debug/txsource/workload/registration.go @@ -243,30 +243,12 @@ func (r *registration) Run( // nolint: gocyclo // Estimate gas and submit transaction. tx := registry.NewRegisterEntityTx(entityAccs[i].reckonedNonce, &transaction.Fee{}, sigEntity) entityAccs[i].reckonedNonce++ - gas, err := cnsc.EstimateGas(ctx, &consensus.EstimateGasRequest{ - Caller: entityAccs[i].signer.Public(), - Transaction: tx, - }) - if err != nil { - return fmt.Errorf("failed to estimate gas: %w", err) - } - tx.Fee.Gas = gas - feeAmount := int64(gas) * gasPrice - if err = tx.Fee.Amount.FromInt64(feeAmount); err != nil { - return fmt.Errorf("fee amount from int64: %w", err) - } - - // Fund entity account to cover registration fees. - if err = transferFunds(ctx, registrationLogger, cnsc, fundingAccount, entityAccs[i].signer.Public(), feeAmount); err != nil { - return fmt.Errorf("account funding failure: %w", err) - } - - signedTx, err := transaction.Sign(entityAccs[i].signer, tx) - if err != nil { - return fmt.Errorf("transaction.Sign: %w", err) - } - if err = cnsc.SubmitTx(ctx, signedTx); err != nil { - return fmt.Errorf("cnsc.SubmitTx: %w", err) + if err := fundSignAndSubmitTx(ctx, registrationLogger, cnsc, entityAccs[i].signer, tx, fundingAccount); err != nil { + registrationLogger.Error("failed to sign and submit regsiter entity transaction", + "tx", tx, + "signer", entityAccs[i].signer, + ) + return fmt.Errorf("failed to sign and submit tx: %w", err) } // Register runtime. @@ -280,31 +262,13 @@ func (r *registration) Run( // nolint: gocyclo } tx := registry.NewRegisterRuntimeTx(entityAccs[i].reckonedNonce, &transaction.Fee{}, sigRuntime) - gas, err := cnsc.EstimateGas(ctx, &consensus.EstimateGasRequest{ - Caller: entityAccs[i].signer.Public(), - Transaction: tx, - }) - if err != nil { - return fmt.Errorf("failed to estimate gas: %w", err) - } - tx.Fee.Gas = gas - feeAmount := int64(gas) * gasPrice - if err = tx.Fee.Amount.FromInt64(feeAmount); err != nil { - return fmt.Errorf("fee amount from uint64: %w", err) - } - - // Fund entity account to cover entity registration fees. - if err = transferFunds(ctx, registrationLogger, cnsc, fundingAccount, entityAccs[i].signer.Public(), feeAmount); err != nil { - return fmt.Errorf("account funding failure: %w", err) - } - entityAccs[i].reckonedNonce++ - signedTx, err := transaction.Sign(entityAccs[i].signer, tx) - if err != nil { - return fmt.Errorf("transaction.Sign: %w", err) - } - if err = cnsc.SubmitTx(ctx, signedTx); err != nil { - return fmt.Errorf("cnsc.SubmitTx: %w", err) + if err := fundSignAndSubmitTx(ctx, registrationLogger, cnsc, entityAccs[i].signer, tx, fundingAccount); err != nil { + registrationLogger.Error("failed to sign and submit register runtime transaction", + "tx", tx, + "signer", entityAccs[i].signer, + ) + return fmt.Errorf("failed to sign and submit tx: %w", err) } } } @@ -331,35 +295,15 @@ func (r *registration) Run( // nolint: gocyclo // Register node. tx := registry.NewRegisterNodeTx(selectedNode.reckonedNonce, &transaction.Fee{}, sigNode) - gas, err := cnsc.EstimateGas(ctx, &consensus.EstimateGasRequest{ - Caller: selectedNode.id.NodeSigner.Public(), - Transaction: tx, - }) - if err != nil { - return fmt.Errorf("failed to estimate gas: %w", err) - } - tx.Fee.Gas = gas - feeAmount := gas * gasPrice - if err = tx.Fee.Amount.FromUint64(uint64(feeAmount)); err != nil { - return fmt.Errorf("fee amount from uint64: %w", err) - } - - // Fund node account to cover registration fees. - if err = transferFunds(ctx, registrationLogger, cnsc, fundingAccount, selectedNode.id.NodeSigner.Public(), int64(feeAmount)); err != nil { - return fmt.Errorf("account funding failure: %w", err) - } selectedNode.reckonedNonce++ - - signedTx, err := transaction.Sign(selectedNode.id.NodeSigner, tx) - if err != nil { - return fmt.Errorf("transaction.Sign: %w", err) - } - registrationLogger.Debug("submitting registration", - "node", selectedNode.nodeDesc, - ) - if err = cnsc.SubmitTx(ctx, signedTx); err != nil { - return fmt.Errorf("cnsc.SubmitTx: %w", err) + if err := fundSignAndSubmitTx(ctx, registrationLogger, cnsc, selectedNode.id.NodeSigner, tx, fundingAccount); err != nil { + registrationLogger.Error("failed to sign and submit register node transaction", + "tx", tx, + "signer", selectedNode.id.NodeSigner, + ) + return fmt.Errorf("failed to sign and submit tx: %w", err) } + registrationLogger.Debug("registered node", "node", selectedNode.nodeDesc, ) diff --git a/go/oasis-node/cmd/debug/txsource/workload/workload.go b/go/oasis-node/cmd/debug/txsource/workload/workload.go index 4df4982937a..73a17995640 100644 --- a/go/oasis-node/cmd/debug/txsource/workload/workload.go +++ b/go/oasis-node/cmd/debug/txsource/workload/workload.go @@ -33,6 +33,60 @@ func FundAccountFromTestEntity(ctx context.Context, logger *logging.Logger, cnsc return transferFunds(ctx, logger, cnsc, testEntitySigner, to, fundAccountAmount) } +func fundSignAndSubmitTx(ctx context.Context, logger *logging.Logger, cnsc consensus.ClientBackend, caller signature.Signer, tx *transaction.Transaction, fundingAccount signature.Signer) error { + // Estimate gas needed if not set. + if tx.Fee.Gas == 0 { + gas, err := cnsc.EstimateGas(ctx, &consensus.EstimateGasRequest{ + Caller: caller.Public(), + Transaction: tx, + }) + if err != nil { + return fmt.Errorf("failed to estimate gas: %w", err) + } + tx.Fee.Gas = gas + } + + // Fund caller to cover transaction fees. + feeAmount := int64(tx.Fee.Gas) * gasPrice + if err := tx.Fee.Amount.FromInt64(feeAmount); err != nil { + return fmt.Errorf("fee amount from int64: %w", err) + } + if err := transferFunds(ctx, logger, cnsc, fundingAccount, caller.Public(), feeAmount); err != nil { + return fmt.Errorf("account funding failure: %w", err) + } + + // Sign tx. + signedTx, err := transaction.Sign(caller, tx) + if err != nil { + return fmt.Errorf("transaction.Sign: %w", err) + } + + logger.Debug("submitting transaction", + "tx", tx, + "signed_tx", signedTx, + "caller", caller, + ) + + // SubmitTx. + // Wait for a maximum of 60 seconds to submit transaction. + submitCtx, cancel := context.WithTimeout(ctx, 60*time.Second) + err = cnsc.SubmitTx(submitCtx, signedTx) + switch err { + case nil: + cancel() + return nil + default: + cancel() + logger.Error("failed to submit transaction", + "err", err, + "tx", tx, + "signed_tx", signedTx, + "caller", caller, + ) + return fmt.Errorf("cnsc.SubmitTx: %w", err) + } +} + // transferFunds transfer funds between accounts. func transferFunds(ctx context.Context, logger *logging.Logger, cnsc consensus.ClientBackend, from signature.Signer, to signature.PublicKey, transferAmount int64) error { sched := backoff.NewExponentialBackOff()