mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 17:44:29 +00:00
283 lines
8.6 KiB
Go
283 lines
8.6 KiB
Go
package freezeblocks_test
|
|
|
|
import (
|
|
"github.com/ledgerwatch/erigon/polygon/bor/borcfg"
|
|
"math/big"
|
|
"testing"
|
|
|
|
"github.com/holiman/uint256"
|
|
"github.com/ledgerwatch/erigon-lib/chain/networkname"
|
|
"github.com/ledgerwatch/erigon-lib/chain/snapcfg"
|
|
"github.com/ledgerwatch/log/v3"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/chain"
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
types2 "github.com/ledgerwatch/erigon-lib/types"
|
|
|
|
"github.com/ledgerwatch/erigon/common/math"
|
|
"github.com/ledgerwatch/erigon/core"
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
"github.com/ledgerwatch/erigon/crypto"
|
|
"github.com/ledgerwatch/erigon/ethdb/prune"
|
|
"github.com/ledgerwatch/erigon/params"
|
|
"github.com/ledgerwatch/erigon/rlp"
|
|
"github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks"
|
|
"github.com/ledgerwatch/erigon/turbo/stages/mock"
|
|
)
|
|
|
|
func nonceRange(from, to int) []uint64 {
|
|
a := make([]uint64, to-from+1)
|
|
for i := range a {
|
|
a[i] = uint64(from + i)
|
|
}
|
|
return a
|
|
}
|
|
|
|
func baseIdRange(base, indexer, len int) []uint64 {
|
|
a := make([]uint64, len)
|
|
index := 0
|
|
|
|
for i := range a {
|
|
a[i] = uint64(base + index)
|
|
index += indexer
|
|
}
|
|
return a
|
|
}
|
|
|
|
func TestDump(t *testing.T) {
|
|
type test struct {
|
|
chainConfig *chain.Config
|
|
chainSize int
|
|
}
|
|
|
|
withConfig := func(config chain.Config, sprints map[string]uint64) *chain.Config {
|
|
bor := *config.Bor.(*borcfg.BorConfig)
|
|
bor.Sprint = sprints
|
|
config.Bor = &bor
|
|
return &config
|
|
}
|
|
|
|
tests := []test{
|
|
{
|
|
chainSize: 5,
|
|
chainConfig: params.TestChainConfig,
|
|
},
|
|
{
|
|
chainSize: 50,
|
|
chainConfig: params.TestChainConfig,
|
|
},
|
|
{
|
|
chainSize: 1000,
|
|
chainConfig: params.BorDevnetChainConfig,
|
|
},
|
|
{
|
|
chainSize: 2000,
|
|
chainConfig: params.BorDevnetChainConfig,
|
|
},
|
|
{
|
|
chainSize: 1000,
|
|
chainConfig: withConfig(*params.BorDevnetChainConfig,
|
|
map[string]uint64{
|
|
"0": 64,
|
|
"800": 16,
|
|
"1600": 8,
|
|
}),
|
|
},
|
|
{
|
|
chainSize: 2000,
|
|
chainConfig: withConfig(*params.BorDevnetChainConfig,
|
|
map[string]uint64{
|
|
"0": 64,
|
|
"800": 16,
|
|
"1600": 8,
|
|
}),
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
m := createDumpTestKV(t, test.chainConfig, test.chainSize)
|
|
chainID, _ := uint256.FromBig(m.ChainConfig.ChainID)
|
|
t.Run("txs", func(t *testing.T) {
|
|
require := require.New(t)
|
|
slot := types2.TxSlot{}
|
|
parseCtx := types2.NewTxParseContext(*chainID)
|
|
parseCtx.WithSender(false)
|
|
var sender [20]byte
|
|
|
|
var systemTxs int
|
|
var nonceList []uint64
|
|
cnt, err := freezeblocks.DumpTxs(m.Ctx, m.DB, 0, uint64(2*test.chainSize), m.ChainConfig, 1, log.LvlInfo, log.New(), func(v []byte) error {
|
|
if v == nil {
|
|
systemTxs++
|
|
} else {
|
|
if _, err := parseCtx.ParseTransaction(v[1+20:], 0, &slot, sender[:], false /* hasEnvelope */, false /* wrappedWithBlobs */, nil); err != nil {
|
|
return err
|
|
}
|
|
nonceList = append(nonceList, slot.Nonce)
|
|
}
|
|
return nil
|
|
})
|
|
require.NoError(err)
|
|
require.Equal(2*(test.chainSize+1), systemTxs)
|
|
require.Equal(nonceRange(0, test.chainSize-1), nonceList)
|
|
require.Equal(2*(test.chainSize+1)+test.chainSize, cnt)
|
|
})
|
|
t.Run("txs_not_from_zero", func(t *testing.T) {
|
|
require := require.New(t)
|
|
slot := types2.TxSlot{}
|
|
parseCtx := types2.NewTxParseContext(*chainID)
|
|
parseCtx.WithSender(false)
|
|
var sender [20]byte
|
|
|
|
var systemTxs int
|
|
var nonceList []uint64
|
|
cnt, err := freezeblocks.DumpTxs(m.Ctx, m.DB, 2, uint64(test.chainSize), m.ChainConfig, 1, log.LvlInfo, log.New(), func(v []byte) error {
|
|
if v == nil {
|
|
systemTxs++
|
|
} else {
|
|
if _, err := parseCtx.ParseTransaction(v[1+20:], 0, &slot, sender[:], false /* hasEnvelope */, false /* wrappedWithBlobs */, nil); err != nil {
|
|
return err
|
|
}
|
|
nonceList = append(nonceList, slot.Nonce)
|
|
}
|
|
return nil
|
|
})
|
|
require.NoError(err)
|
|
require.Equal(2*(test.chainSize-2), systemTxs)
|
|
require.Equal(nonceRange(1, test.chainSize-2), nonceList)
|
|
require.Equal(3*test.chainSize-6, cnt)
|
|
})
|
|
t.Run("headers", func(t *testing.T) {
|
|
require := require.New(t)
|
|
var nonceList []uint64
|
|
err := freezeblocks.DumpHeaders(m.Ctx, m.DB, 0, uint64(2*test.chainSize), 1, log.LvlInfo, log.New(), func(v []byte) error {
|
|
h := types.Header{}
|
|
if err := rlp.DecodeBytes(v[1:], &h); err != nil {
|
|
return err
|
|
}
|
|
nonceList = append(nonceList, h.Number.Uint64())
|
|
return nil
|
|
})
|
|
require.NoError(err)
|
|
require.Equal(nonceRange(0, test.chainSize), nonceList)
|
|
})
|
|
t.Run("headers_not_from_zero", func(t *testing.T) {
|
|
require := require.New(t)
|
|
var nonceList []uint64
|
|
err := freezeblocks.DumpHeaders(m.Ctx, m.DB, 2, uint64(test.chainSize), 1, log.LvlInfo, log.New(), func(v []byte) error {
|
|
h := types.Header{}
|
|
if err := rlp.DecodeBytes(v[1:], &h); err != nil {
|
|
return err
|
|
}
|
|
nonceList = append(nonceList, h.Number.Uint64())
|
|
return nil
|
|
})
|
|
require.NoError(err)
|
|
require.Equal(nonceRange(2, test.chainSize-1), nonceList)
|
|
})
|
|
t.Run("body", func(t *testing.T) {
|
|
require := require.New(t)
|
|
i := 0
|
|
txsAmount := uint64(0)
|
|
var baseIdList []uint64
|
|
firstTxNum := uint64(0)
|
|
_, err := freezeblocks.DumpBodies(m.Ctx, m.DB, 0, uint64(test.chainSize-3), firstTxNum, log.LvlInfo, log.New(), func(v []byte) error {
|
|
i++
|
|
body := &types.BodyForStorage{}
|
|
require.NoError(rlp.DecodeBytes(v, body))
|
|
txsAmount += uint64(body.TxAmount)
|
|
baseIdList = append(baseIdList, body.BaseTxId)
|
|
return nil
|
|
})
|
|
require.NoError(err)
|
|
require.Equal(test.chainSize-3, i)
|
|
require.Equal(3*(test.chainSize-3)-1, int(txsAmount))
|
|
require.Equal(append([]uint64{0}, baseIdRange(2, 3, test.chainSize-4)...), baseIdList)
|
|
|
|
firstTxNum += txsAmount
|
|
i = 0
|
|
baseIdList = baseIdList[:0]
|
|
_, err = freezeblocks.DumpBodies(m.Ctx, m.DB, 2, uint64(2*test.chainSize), firstTxNum, log.LvlInfo, log.New(), func(v []byte) error {
|
|
i++
|
|
body := &types.BodyForStorage{}
|
|
require.NoError(rlp.DecodeBytes(v, body))
|
|
txsAmount += uint64(body.TxAmount)
|
|
baseIdList = append(baseIdList, body.BaseTxId)
|
|
return nil
|
|
})
|
|
require.NoError(err)
|
|
require.Equal(test.chainSize-1, i)
|
|
require.Equal(firstTxNum+uint64(3*(test.chainSize-1)), txsAmount)
|
|
require.Equal(baseIdRange(int(firstTxNum), 3, test.chainSize-1), baseIdList)
|
|
})
|
|
t.Run("body_not_from_zero", func(t *testing.T) {
|
|
require := require.New(t)
|
|
i := 0
|
|
var baseIdList []uint64
|
|
firstTxNum := uint64(1000)
|
|
lastTxNum, err := freezeblocks.DumpBodies(m.Ctx, m.DB, 2, uint64(test.chainSize), firstTxNum, log.LvlInfo, log.New(), func(v []byte) error {
|
|
i++
|
|
body := &types.BodyForStorage{}
|
|
require.NoError(rlp.DecodeBytes(v, body))
|
|
baseIdList = append(baseIdList, body.BaseTxId)
|
|
return nil
|
|
})
|
|
require.NoError(err)
|
|
require.Equal(test.chainSize-2, i)
|
|
require.Equal(baseIdRange(int(firstTxNum), 3, test.chainSize-2), baseIdList)
|
|
require.Equal(lastTxNum, baseIdList[len(baseIdList)-1]+3)
|
|
require.Equal(lastTxNum, firstTxNum+uint64(i*3))
|
|
})
|
|
t.Run("blocks", func(t *testing.T) {
|
|
if test.chainSize < 1000 || test.chainSize%1000 != 0 {
|
|
t.Skip("Block dump requires chain size to be a multiple of 1000")
|
|
}
|
|
|
|
require := require.New(t)
|
|
|
|
logger := log.New()
|
|
|
|
tmpDir, snapDir := t.TempDir(), t.TempDir()
|
|
snConfig := snapcfg.KnownCfg(networkname.MainnetChainName, 0)
|
|
snConfig.ExpectBlocks = math.MaxUint64
|
|
|
|
err := freezeblocks.DumpBlocks(m.Ctx, 1, 0, uint64(test.chainSize), uint64(test.chainSize), tmpDir, snapDir, m.DB, 1, log.LvlInfo, logger, m.BlockReader)
|
|
require.NoError(err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func createDumpTestKV(t *testing.T, chainConfig *chain.Config, chainSize int) *mock.MockSentry {
|
|
var (
|
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
|
addr = crypto.PubkeyToAddress(key.PublicKey)
|
|
gspec = &types.Genesis{
|
|
Config: chainConfig,
|
|
Alloc: types.GenesisAlloc{addr: {Balance: (&big.Int{}).Mul(big.NewInt(math.MaxInt64), big.NewInt(int64(chainSize)))}},
|
|
}
|
|
signer = types.LatestSigner(gspec.Config)
|
|
)
|
|
|
|
m := mock.MockWithGenesisPruneMode(t, gspec, key, chainSize, prune.DefaultMode, false)
|
|
|
|
// Generate testing blocks
|
|
chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, chainSize, func(i int, b *core.BlockGen) {
|
|
b.SetCoinbase(libcommon.Address{1})
|
|
tx, txErr := types.SignTx(types.NewTransaction(b.TxNonce(addr), libcommon.HexToAddress("deadbeef"), uint256.NewInt(100), 21000, uint256.NewInt(uint64(int64(i+1)*params.GWei)), nil), *signer, key)
|
|
if txErr != nil {
|
|
t.Fatalf("failed to create tx: %v", txErr)
|
|
}
|
|
b.AddTx(tx)
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Construct testing chain
|
|
if err = m.InsertChain(chain); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return m
|
|
}
|