2023-05-24 08:52:51 +00:00
|
|
|
package migrations_test
|
2022-03-10 07:48:58 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/binary"
|
2023-05-24 08:52:51 +00:00
|
|
|
"fmt"
|
2022-03-10 07:48:58 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2023-01-13 18:12:18 +00:00
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/common/hexutility"
|
2022-03-10 07:48:58 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/common/u256"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/kv/memdb"
|
2023-05-24 08:52:51 +00:00
|
|
|
"github.com/ledgerwatch/erigon/migrations"
|
2023-05-10 18:36:27 +00:00
|
|
|
"github.com/ledgerwatch/log/v3"
|
2023-01-13 18:12:18 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2022-03-10 07:48:58 +00:00
|
|
|
"github.com/ledgerwatch/erigon/core/rawdb"
|
|
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
|
|
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestTxsBeginEnd(t *testing.T) {
|
|
|
|
require, tmpDir, db := require.New(t), t.TempDir(), memdb.NewTestDB(t)
|
2023-06-14 09:44:05 +00:00
|
|
|
txn := &types.DynamicFeeTransaction{Tip: u256.N1, FeeCap: u256.N1, ChainID: u256.N1, CommonTx: types.CommonTx{Value: u256.N1, Gas: 1, Nonce: 1}}
|
2022-03-10 07:48:58 +00:00
|
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
err := txn.MarshalBinary(buf)
|
|
|
|
require.NoError(err)
|
|
|
|
rlpTxn := buf.Bytes()
|
|
|
|
logEvery := time.NewTicker(10 * time.Second)
|
|
|
|
defer logEvery.Stop()
|
|
|
|
|
|
|
|
b := &types.RawBody{Transactions: [][]byte{rlpTxn, rlpTxn, rlpTxn}}
|
|
|
|
err = db.Update(context.Background(), func(tx kv.RwTx) error {
|
|
|
|
for i := uint64(0); i < 10; i++ {
|
2023-01-13 18:12:18 +00:00
|
|
|
hash := libcommon.Hash{byte(i)}
|
2022-03-10 07:48:58 +00:00
|
|
|
err = writeRawBodyDeprecated(tx, hash, i, b)
|
|
|
|
require.NoError(err)
|
|
|
|
err = rawdb.WriteCanonicalHash(tx, hash, i)
|
|
|
|
require.NoError(err)
|
|
|
|
}
|
2023-05-24 08:52:51 +00:00
|
|
|
if err := migrations.MakeBodiesNonCanonicalDeprecated(tx, 7, context.Background(), "", logEvery); err != nil {
|
2022-03-10 07:48:58 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-06-24 13:52:04 +00:00
|
|
|
err = rawdb.TruncateCanonicalHash(tx, 7, false)
|
2022-03-10 07:48:58 +00:00
|
|
|
for i := uint64(7); i < 10; i++ {
|
|
|
|
require.NoError(err)
|
2023-01-13 18:12:18 +00:00
|
|
|
hash := libcommon.Hash{0xa, byte(i)}
|
2022-03-10 07:48:58 +00:00
|
|
|
err = writeRawBodyDeprecated(tx, hash, i, b)
|
|
|
|
require.NoError(err)
|
|
|
|
err = rawdb.WriteCanonicalHash(tx, hash, i)
|
|
|
|
require.NoError(err)
|
|
|
|
}
|
|
|
|
if err := stages.SaveStageProgress(tx, stages.Bodies, 9); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(err)
|
|
|
|
|
2023-05-24 08:52:51 +00:00
|
|
|
migrator := migrations.NewMigrator(kv.ChainDB)
|
|
|
|
migrator.Migrations = []migrations.Migration{migrations.TxsBeginEnd}
|
2023-05-10 18:36:27 +00:00
|
|
|
logger := log.New()
|
|
|
|
err = migrator.Apply(db, tmpDir, logger)
|
2022-03-10 07:48:58 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
|
|
|
v, err := tx.ReadSequence(kv.EthTx)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal(uint64(3*10+2*10), v)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
|
|
|
for i := uint64(7); i < 10; i++ {
|
2023-01-13 18:12:18 +00:00
|
|
|
hash := libcommon.Hash{byte(i)}
|
2022-03-10 07:48:58 +00:00
|
|
|
k := make([]byte, 8+32)
|
|
|
|
binary.BigEndian.PutUint64(k, 7)
|
|
|
|
copy(k[8:], hash[:])
|
|
|
|
|
|
|
|
has, err := tx.Has(kv.BlockBody, k)
|
|
|
|
require.NoError(err)
|
|
|
|
require.False(has)
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := tx.Cursor(kv.NonCanonicalTxs)
|
|
|
|
require.NoError(err)
|
|
|
|
cnt, err := c.Count()
|
|
|
|
require.NoError(err)
|
|
|
|
require.Zero(cnt)
|
|
|
|
|
|
|
|
v, err := tx.ReadSequence(kv.NonCanonicalTxs)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Zero(v)
|
|
|
|
|
2023-01-13 18:12:18 +00:00
|
|
|
has, err := tx.Has(kv.EthTx, hexutility.EncodeTs(0))
|
2022-03-10 07:48:58 +00:00
|
|
|
require.NoError(err)
|
|
|
|
require.False(has)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
}
|
2023-05-24 08:52:51 +00:00
|
|
|
|
|
|
|
func writeRawBodyDeprecated(db kv.RwTx, hash libcommon.Hash, number uint64, body *types.RawBody) error {
|
|
|
|
baseTxId, err := db.IncrementSequence(kv.EthTx, uint64(len(body.Transactions)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
data := types.BodyForStorage{
|
|
|
|
BaseTxId: baseTxId,
|
|
|
|
TxAmount: uint32(len(body.Transactions)),
|
|
|
|
Uncles: body.Uncles,
|
|
|
|
}
|
|
|
|
if err = rawdb.WriteBodyForStorage(db, hash, number, &data); err != nil {
|
|
|
|
return fmt.Errorf("failed to write body: %w", err)
|
|
|
|
}
|
|
|
|
if err = writeRawTransactionsDeprecated(db, body.Transactions, baseTxId); err != nil {
|
|
|
|
return fmt.Errorf("failed to WriteRawTransactions: %w, blockNum=%d", err, number)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func writeRawTransactionsDeprecated(tx kv.RwTx, txs [][]byte, baseTxId uint64) error {
|
|
|
|
txId := baseTxId
|
|
|
|
for _, txn := range txs {
|
|
|
|
txIdKey := make([]byte, 8)
|
|
|
|
binary.BigEndian.PutUint64(txIdKey, txId)
|
|
|
|
// If next Append returns KeyExists error - it means you need to open transaction in App code before calling this func. Batch is also fine.
|
|
|
|
if err := tx.Append(kv.EthTx, txIdKey, txn); err != nil {
|
|
|
|
return fmt.Errorf("txId=%d, baseTxId=%d, %w", txId, baseTxId, err)
|
|
|
|
}
|
|
|
|
txId++
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|