erigon-pulse/migrations/txs_begin_end_test.go
Andrew Ashikhmin 862d7b6bc6
Move ChainID from CommonTx to DynamicFeeTransaction (#7732)
For legacy transactions ChainID is optional (missing in
pre-[EIP155](https://eips.ethereum.org/EIPS/eip-155) transactions) and
is derived from `V` anyway.

Also, cherry pick https://github.com/ethereum/go-ethereum/pull/27452.
2023-06-14 11:44:05 +02:00

142 lines
4.1 KiB
Go

package migrations_test
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"testing"
"time"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/hexutility"
"github.com/ledgerwatch/erigon-lib/common/u256"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon/migrations"
"github.com/ledgerwatch/log/v3"
"github.com/stretchr/testify/require"
"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)
txn := &types.DynamicFeeTransaction{Tip: u256.N1, FeeCap: u256.N1, ChainID: u256.N1, CommonTx: types.CommonTx{Value: u256.N1, Gas: 1, Nonce: 1}}
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++ {
hash := libcommon.Hash{byte(i)}
err = writeRawBodyDeprecated(tx, hash, i, b)
require.NoError(err)
err = rawdb.WriteCanonicalHash(tx, hash, i)
require.NoError(err)
}
if err := migrations.MakeBodiesNonCanonicalDeprecated(tx, 7, context.Background(), "", logEvery); err != nil {
return err
}
err = rawdb.TruncateCanonicalHash(tx, 7, false)
for i := uint64(7); i < 10; i++ {
require.NoError(err)
hash := libcommon.Hash{0xa, byte(i)}
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)
migrator := migrations.NewMigrator(kv.ChainDB)
migrator.Migrations = []migrations.Migration{migrations.TxsBeginEnd}
logger := log.New()
err = migrator.Apply(db, tmpDir, logger)
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++ {
hash := libcommon.Hash{byte(i)}
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)
has, err := tx.Has(kv.EthTx, hexutility.EncodeTs(0))
require.NoError(err)
require.False(has)
return nil
})
require.NoError(err)
}
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
}