block-sdk/block/utils/decoder_test.go
David Terpay bfdd58411a
feat: Cache Tx Decoder (#528)
* init

* nit

* nits

* nit

* more nits

* go version bump

* image bump

* nit
2024-06-20 17:03:22 -04:00

219 lines
5.0 KiB
Go

package utils_test
import (
"math/rand"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/skip-mev/block-sdk/v2/block/utils"
"github.com/skip-mev/block-sdk/v2/testutils"
)
var (
numAccounts = 5
numTxsPerAcct = 100
cacheSize = 500
)
func BenchmarkCacheDecoding(b *testing.B) {
encodingCfg := testutils.CreateTestEncodingConfig()
decoder := encodingCfg.TxConfig.TxDecoder()
random := rand.New(rand.NewSource(time.Now().Unix()))
account := testutils.RandomAccounts(random, numAccounts)
txs := make([][]byte, numAccounts*numTxsPerAcct)
for i := 0; i < numAccounts; i++ {
for j := 0; j < numTxsPerAcct; j++ {
txBytes, err := testutils.CreateRandomTxBz(
encodingCfg.TxConfig,
account[i],
uint64(j),
1,
2,
0,
)
require.NoError(b, err)
txs[i*numTxsPerAcct+j] = txBytes
}
}
cacheTxDecoder, err := utils.NewCacheTxDecoder(decoder, uint64(cacheSize))
require.NoError(b, err)
decoder = cacheTxDecoder.TxDecoder()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, txBytes := range txs {
_, err := decoder(txBytes)
require.NoError(b, err)
}
for _, txBytes := range txs {
_, err := decoder(txBytes)
require.NoError(b, err)
}
}
}
func BenchmarkStandardDecoding(b *testing.B) {
encodingCfg := testutils.CreateTestEncodingConfig()
decoder := encodingCfg.TxConfig.TxDecoder()
random := rand.New(rand.NewSource(time.Now().Unix()))
account := testutils.RandomAccounts(random, numAccounts)
txs := make([][]byte, numAccounts*numTxsPerAcct)
for i := 0; i < numAccounts; i++ {
for j := 0; j < numTxsPerAcct; j++ {
txBytes, err := testutils.CreateRandomTxBz(
encodingCfg.TxConfig,
account[i],
uint64(j),
1,
2,
0,
)
require.NoError(b, err)
txs[i*numTxsPerAcct+j] = txBytes
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, txBytes := range txs {
_, err := decoder(txBytes)
require.NoError(b, err)
}
for _, txBytes := range txs {
_, err := decoder(txBytes)
require.NoError(b, err)
}
}
}
func TestNewCacheTxDecoder(t *testing.T) {
encodingCfg := testutils.CreateTestEncodingConfig()
decoder := encodingCfg.TxConfig.TxDecoder()
_, err := utils.NewDefaultCacheTxDecoder(decoder)
require.NoError(t, err)
_, err = utils.NewCacheTxDecoder(decoder, 100)
require.NoError(t, err)
_, err = utils.NewCacheTxDecoder(nil, 100)
require.Error(t, err)
}
func TestDecode(t *testing.T) {
encodingCfg := testutils.CreateTestEncodingConfig()
decoder := encodingCfg.TxConfig.TxDecoder()
random := rand.New(rand.NewSource(time.Now().Unix()))
account := testutils.RandomAccounts(random, 1)
t.Run("decode valid tx and check that it is cached", func(t *testing.T) {
txBytes, err := testutils.CreateRandomTxBz(
encodingCfg.TxConfig,
account[0],
0,
1,
1,
0,
)
require.NoError(t, err)
cacheTxDecoder, err := utils.NewDefaultCacheTxDecoder(decoder)
require.NoError(t, err)
decoder := cacheTxDecoder.TxDecoder()
tx, err := decoder(txBytes)
require.NoError(t, err)
require.NotNil(t, tx)
require.Equal(t, 1, cacheTxDecoder.Len())
require.True(t, cacheTxDecoder.Contains(txBytes))
// decode the same tx again
tx, err = decoder(txBytes)
require.NoError(t, err)
require.NotNil(t, tx)
require.Equal(t, 1, cacheTxDecoder.Len())
require.True(t, cacheTxDecoder.Contains(txBytes))
})
t.Run("decode invalid tx", func(t *testing.T) {
cacheTxDecoder, err := utils.NewDefaultCacheTxDecoder(decoder)
require.NoError(t, err)
decoder := cacheTxDecoder.TxDecoder()
tx, err := decoder([]byte("invalid tx"))
require.Error(t, err)
require.Nil(t, tx)
require.Equal(t, 0, cacheTxDecoder.Len())
})
t.Run("decode multiple txs without hitting limit", func(t *testing.T) {
cacheTxDecoder, err := utils.NewCacheTxDecoder(decoder, 100)
require.NoError(t, err)
for i := 0; i < 100; i++ {
txBytes, err := testutils.CreateRandomTxBz(
encodingCfg.TxConfig,
account[0],
uint64(i),
1,
1,
0,
)
require.NoError(t, err)
decoder := cacheTxDecoder.TxDecoder()
tx, err := decoder(txBytes)
require.NoError(t, err)
require.NotNil(t, tx)
require.Equal(t, i+1, cacheTxDecoder.Len())
require.True(t, cacheTxDecoder.Contains(txBytes))
}
require.Equal(t, 100, cacheTxDecoder.Len())
})
t.Run("decode multiple txs hitting limit", func(t *testing.T) {
maxSize := uint64(2)
cacheTxDecoder, err := utils.NewCacheTxDecoder(decoder, maxSize)
require.NoError(t, err)
for i := 0; i < int(maxSize*3); i++ {
txBytes, err := testutils.CreateRandomTxBz(
encodingCfg.TxConfig,
account[0],
uint64(i),
1,
1,
0,
)
require.NoError(t, err)
decoder := cacheTxDecoder.TxDecoder()
tx, err := decoder(txBytes)
require.NoError(t, err)
require.NotNil(t, tx)
require.True(t, cacheTxDecoder.Contains(txBytes))
if i < int(maxSize) {
require.Equal(t, i+1, cacheTxDecoder.Len())
} else {
require.Equal(t, int(maxSize), cacheTxDecoder.Len())
}
}
require.Equal(t, int(maxSize), cacheTxDecoder.Len())
})
}