feat: backport unordered transactions (#23708)
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> Co-authored-by: yihuang <huang@crypto.com> Co-authored-by: Facundo <facundomedica@gmail.com> Co-authored-by: Facundo Medica <14063057+facundomedica@users.noreply.github.com> Co-authored-by: Alex | Interchain Labs <alex@interchainlabs.io>
This commit is contained in:
co-authored by
Aleksandr Bezobchuk
yihuang
Facundo
Facundo Medica
Alex | Interchain Labs
parent
ff779eca8d
commit
7f7c41e4aa
+48
-39
@@ -21,7 +21,7 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// ValidatorStore defines the interface contract require for verifying vote
|
||||
// ValidatorStore defines the interface contract required for verifying vote
|
||||
// extension signatures. Typically, this will be implemented by the x/staking
|
||||
// module, which has knowledge of the CometBFT public key.
|
||||
ValidatorStore interface {
|
||||
@@ -83,7 +83,7 @@ func ValidateVoteExtensions(
|
||||
totalVP += vote.Validator.Power
|
||||
|
||||
// Only check + include power if the vote is a commit vote. There must be super-majority, otherwise the
|
||||
// previous block (the block vote is for) could not have been committed.
|
||||
// previous block (the block the vote is for) could not have been committed.
|
||||
if vote.BlockIdFlag != cmtproto.BlockIDFlagCommit {
|
||||
continue
|
||||
}
|
||||
@@ -286,35 +286,41 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
|
||||
invalidTxs []sdk.Tx // invalid txs to be removed out of the loop to avoid dead lock
|
||||
)
|
||||
mempool.SelectBy(ctx, h.mempool, req.Txs, func(memTx sdk.Tx) bool {
|
||||
signerData, err := h.signerExtAdapter.GetSigners(memTx)
|
||||
if err != nil {
|
||||
// propagate the error to the caller
|
||||
resError = err
|
||||
return false
|
||||
}
|
||||
|
||||
// If the signers aren't in selectedTxsSignersSeqs then we haven't seen them before
|
||||
// so we add them and continue given that we don't need to check the sequence.
|
||||
shouldAdd := true
|
||||
unorderedTx, ok := memTx.(sdk.TxWithUnordered)
|
||||
isUnordered := ok && unorderedTx.GetUnordered()
|
||||
txSignersSeqs := make(map[string]uint64)
|
||||
for _, signer := range signerData {
|
||||
seq, ok := selectedTxsSignersSeqs[signer.Signer.String()]
|
||||
if !ok {
|
||||
txSignersSeqs[signer.Signer.String()] = signer.Sequence
|
||||
continue
|
||||
|
||||
// if the tx is unordered, we don't need to check the sequence, we just add it
|
||||
if !isUnordered {
|
||||
signerData, err := h.signerExtAdapter.GetSigners(memTx)
|
||||
if err != nil {
|
||||
// propagate the error to the caller
|
||||
resError = err
|
||||
return false
|
||||
}
|
||||
|
||||
// If we have seen this signer before in this block, we must make
|
||||
// sure that the current sequence is seq+1; otherwise is invalid
|
||||
// and we skip it.
|
||||
if seq+1 != signer.Sequence {
|
||||
shouldAdd = false
|
||||
break
|
||||
// If the signers aren't in selectedTxsSignersSeqs then we haven't seen them before
|
||||
// so we add them and continue given that we don't need to check the sequence.
|
||||
shouldAdd := true
|
||||
for _, signer := range signerData {
|
||||
seq, ok := selectedTxsSignersSeqs[signer.Signer.String()]
|
||||
if !ok {
|
||||
txSignersSeqs[signer.Signer.String()] = signer.Sequence
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have seen this signer before in this block, we must make
|
||||
// sure that the current sequence is seq+1; otherwise is invalid
|
||||
// and we skip it.
|
||||
if seq+1 != signer.Sequence {
|
||||
shouldAdd = false
|
||||
break
|
||||
}
|
||||
txSignersSeqs[signer.Signer.String()] = signer.Sequence
|
||||
}
|
||||
if !shouldAdd {
|
||||
return true
|
||||
}
|
||||
txSignersSeqs[signer.Signer.String()] = signer.Sequence
|
||||
}
|
||||
if !shouldAdd {
|
||||
return true
|
||||
}
|
||||
|
||||
// NOTE: Since transaction verification was already executed in CheckTx,
|
||||
@@ -331,18 +337,21 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
|
||||
}
|
||||
|
||||
txsLen := len(h.txSelector.SelectedTxs(ctx))
|
||||
for sender, seq := range txSignersSeqs {
|
||||
// If txsLen != selectedTxsNums is true, it means that we've
|
||||
// added a new tx to the selected txs, so we need to update
|
||||
// the sequence of the sender.
|
||||
if txsLen != selectedTxsNums {
|
||||
selectedTxsSignersSeqs[sender] = seq
|
||||
} else if _, ok := selectedTxsSignersSeqs[sender]; !ok {
|
||||
// The transaction hasn't been added but it passed the
|
||||
// verification, so we know that the sequence is correct.
|
||||
// So we set this sender's sequence to seq-1, in order
|
||||
// to avoid unnecessary calls to PrepareProposalVerifyTx.
|
||||
selectedTxsSignersSeqs[sender] = seq - 1
|
||||
// If the tx is unordered, we don't need to update the sender sequence.
|
||||
if !isUnordered {
|
||||
for sender, seq := range txSignersSeqs {
|
||||
// If txsLen != selectedTxsNums is true, it means that we've
|
||||
// added a new tx to the selected txs, so we need to update
|
||||
// the sequence of the sender.
|
||||
if txsLen != selectedTxsNums {
|
||||
selectedTxsSignersSeqs[sender] = seq
|
||||
} else if _, ok := selectedTxsSignersSeqs[sender]; !ok {
|
||||
// The transaction hasn't been added but it passed the
|
||||
// verification, so we know that the sequence is correct.
|
||||
// So we set this sender's sequence to seq-1, in order
|
||||
// to avoid unnecessary calls to PrepareProposalVerifyTx.
|
||||
selectedTxsSignersSeqs[sender] = seq - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
selectedTxsNums = txsLen
|
||||
|
||||
@@ -85,7 +85,6 @@ func TestBaseApp_BlockGas(t *testing.T) {
|
||||
configurator.NewAppConfig(
|
||||
configurator.AuthModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.ParamsModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.StakingModule(),
|
||||
@@ -115,12 +114,13 @@ func TestBaseApp_BlockGas(t *testing.T) {
|
||||
genState := GenesisStateWithSingleValidator(t, cdc, appBuilder)
|
||||
stateBytes, err := cmtjson.MarshalIndent(genState, "", " ")
|
||||
require.NoError(t, err)
|
||||
bapp.InitChain(&abci.RequestInitChain{
|
||||
_, err = bapp.InitChain(&abci.RequestInitChain{
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
ConsensusParams: simtestutil.DefaultConsensusParams,
|
||||
AppStateBytes: stateBytes,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
ctx := bapp.NewContext(false)
|
||||
|
||||
// tx fee
|
||||
|
||||
Reference in New Issue
Block a user