BRG4-20.3: pass current block number in to NewPoLTx for more clarity

This commit is contained in:
Cal Bera 2025-08-15 10:17:50 -07:00
parent 1301bf6f44
commit ac2da12e2f
6 changed files with 54 additions and 21 deletions

View file

@ -19,7 +19,6 @@ package core
import ( import (
"errors" "errors"
"fmt" "fmt"
"math/big"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
@ -100,7 +99,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
polTx, err := types.NewPoLTx( polTx, err := types.NewPoLTx(
v.config.ChainID, v.config.ChainID,
v.config.Berachain.Prague1.PoLDistributorAddress, v.config.Berachain.Prague1.PoLDistributorAddress,
new(big.Int).Sub(block.Number(), big.NewInt(1)), block.Number(),
params.PoLTxGasLimit, params.PoLTxGasLimit,
block.BaseFee(), block.BaseFee(),
block.ProposerPubkey(), block.ProposerPubkey(),

View file

@ -93,7 +93,7 @@ func TestValidateBody_Prague1_Valid(t *testing.T) {
chain, validator := buildTestChain(t, cfg) chain, validator := buildTestChain(t, cfg)
// Build PoL tx + dummy tx. // Build PoL tx + dummy tx.
polTx, err := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(0), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey()) polTx, err := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey())
if err != nil { if err != nil {
t.Fatalf("failed to create PoL tx: %v", err) t.Fatalf("failed to create PoL tx: %v", err)
} }
@ -113,7 +113,7 @@ func TestValidateBody_Prague1_InvalidHash(t *testing.T) {
// PoL tx with WRONG pubkey (different from header.ParentProposerPubkey). // PoL tx with WRONG pubkey (different from header.ParentProposerPubkey).
wrongPk := &common.Pubkey{} wrongPk := &common.Pubkey{}
polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(0), params.PoLTxGasLimit, big.NewInt(1000000000), wrongPk) polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), wrongPk)
block := makeBlock(chain.CurrentHeader(), types.Transactions{polTx}, 1) block := makeBlock(chain.CurrentHeader(), types.Transactions{polTx}, 1)
if err := validator.ValidateBody(block); err == nil { if err := validator.ValidateBody(block); err == nil {
@ -126,7 +126,7 @@ func TestValidateBody_Prague1_MisplacedPoL(t *testing.T) {
cfg := newPrague1Config(distributor) cfg := newPrague1Config(distributor)
chain, validator := buildTestChain(t, cfg) chain, validator := buildTestChain(t, cfg)
polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(0), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey()) polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey())
dummyTx := types.NewTx(&types.LegacyTx{Nonce: 1}) dummyTx := types.NewTx(&types.LegacyTx{Nonce: 1})
// PoL tx placed second. // PoL tx placed second.
block := makeBlock(chain.CurrentHeader(), types.Transactions{dummyTx, polTx}, 1) block := makeBlock(chain.CurrentHeader(), types.Transactions{dummyTx, polTx}, 1)
@ -147,7 +147,7 @@ func TestValidateBody_PrePrague1_PoLProhibited(t *testing.T) {
cfg.Berachain.Prague1.PoLDistributorAddress = distributor cfg.Berachain.Prague1.PoLDistributorAddress = distributor
chain, validator := buildTestChain(t, &cfg) chain, validator := buildTestChain(t, &cfg)
polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(0), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey()) polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey())
block := makeBlock(chain.CurrentHeader(), types.Transactions{polTx}, 1) // timestamp 1 < future block := makeBlock(chain.CurrentHeader(), types.Transactions{polTx}, 1) // timestamp 1 < future
if err := validator.ValidateBody(block); err == nil { if err := validator.ValidateBody(block); err == nil {

View file

@ -45,7 +45,7 @@ type PoLTx struct {
func NewPoLTx( func NewPoLTx(
chainID *big.Int, chainID *big.Int,
distributorAddress common.Address, distributorAddress common.Address,
distributionBlockNumber *big.Int, currentBlockNumber *big.Int,
gasLimit uint64, gasLimit uint64,
baseFee *big.Int, baseFee *big.Int,
pubkey *common.Pubkey, pubkey *common.Pubkey,
@ -54,11 +54,14 @@ func NewPoLTx(
if err != nil { if err != nil {
return nil, err return nil, err
} }
if currentBlockNumber.Sign() <= 0 {
return nil, errors.New("PoL tx must only be created for a block number greater than 0")
}
return NewTx(&PoLTx{ return NewTx(&PoLTx{
ChainID: chainID, ChainID: chainID,
From: params.SystemAddress, From: params.SystemAddress,
To: distributorAddress, To: distributorAddress,
Nonce: distributionBlockNumber.Uint64(), Nonce: currentBlockNumber.Uint64() - 1, // PoL txs are distributing for the previous block
GasLimit: gasLimit, GasLimit: gasLimit,
GasPrice: baseFee, GasPrice: baseFee,
Data: data, Data: data,

View file

@ -86,28 +86,59 @@ func TestNewPoLTx_NilPubkey(t *testing.T) {
} }
} }
// TestNewPoLTx_NegativeBlockNumber ensures negative block numbers are handled // TestNewPoLTx_InvalidBlockNumber ensures that block numbers <= 0 are rejected.
// without panicking (uint64 wrap-around is expected). func TestNewPoLTx_InvalidBlockNumber(t *testing.T) {
func TestNewPoLTx_NegativeBlockNumber(t *testing.T) {
chainID := big.NewInt(1) chainID := big.NewInt(1)
distributor := common.Address{} distributor := common.Address{}
negBlock := big.NewInt(-1)
baseFee := big.NewInt(1000000000) baseFee := big.NewInt(1000000000)
expectedErr := "PoL tx must only be created for a block number greater than 0"
tx, err := NewPoLTx(chainID, distributor, negBlock, params.PoLTxGasLimit, baseFee, samplePubkey()) testCases := []struct {
if err != nil { name string
t.Fatalf("unexpected error: %v", err) blockNumber *big.Int
}{
{"negative block number", big.NewInt(-1)},
{"zero block number", big.NewInt(0)},
} }
if got, want := tx.Nonce(), negBlock.Uint64(); got != want {
t.Fatalf("nonce mismatch: have %d, want %d", got, want) for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tx, err := NewPoLTx(chainID, distributor, tc.blockNumber, params.PoLTxGasLimit, baseFee, samplePubkey())
if err == nil {
t.Fatalf("expected error for block number %v, but got nil", tc.blockNumber)
}
if tx != nil {
t.Fatalf("expected nil transaction when error occurs, but got %v", tx)
}
if err.Error() != expectedErr {
t.Fatalf("error message mismatch: have %q, want %q", err.Error(), expectedErr)
}
})
} }
// Test that positive block numbers work correctly
t.Run("positive block number", func(t *testing.T) {
positiveBlock := big.NewInt(123)
tx, err := NewPoLTx(chainID, distributor, positiveBlock, params.PoLTxGasLimit, baseFee, samplePubkey())
if err != nil {
t.Fatalf("unexpected error for positive block number: %v", err)
}
if tx == nil {
t.Fatalf("expected transaction for positive block number, but got nil")
}
// Nonce should be blockNumber - 1 (as per the implementation)
expectedNonce := positiveBlock.Uint64() - 1
if got := tx.Nonce(); got != expectedNonce {
t.Fatalf("nonce mismatch: have %d, want %d", got, expectedNonce)
}
})
} }
// TestIsPoLDistribution exercises positive and negative cases for the helper. // TestIsPoLDistribution exercises positive and negative cases for the helper.
func TestIsPoLDistribution(t *testing.T) { func TestIsPoLDistribution(t *testing.T) {
distributor := common.HexToAddress("0x1000000000000000000000000000000000000001") distributor := common.HexToAddress("0x1000000000000000000000000000000000000001")
baseFee := big.NewInt(1000000000) baseFee := big.NewInt(1000000000)
tx, err := NewPoLTx(big.NewInt(1), distributor, big.NewInt(0), params.PoLTxGasLimit, baseFee, samplePubkey()) tx, err := NewPoLTx(big.NewInt(1), distributor, big.NewInt(1), params.PoLTxGasLimit, baseFee, samplePubkey())
if err != nil { if err != nil {
t.Fatalf("failed to build PoL tx: %v", err) t.Fatalf("failed to build PoL tx: %v", err)
} }
@ -143,7 +174,7 @@ func TestIsPoLDistribution(t *testing.T) {
// TestPoLTx_RawSignatureValues confirms that PoLTx reports no signature. // TestPoLTx_RawSignatureValues confirms that PoLTx reports no signature.
func TestPoLTx_RawSignatureValues(t *testing.T) { func TestPoLTx_RawSignatureValues(t *testing.T) {
baseFee := big.NewInt(1000000000) baseFee := big.NewInt(1000000000)
tx, err := NewPoLTx(big.NewInt(1), common.Address{}, big.NewInt(0), params.PoLTxGasLimit, baseFee, samplePubkey()) tx, err := NewPoLTx(big.NewInt(1), common.Address{}, big.NewInt(1), params.PoLTxGasLimit, baseFee, samplePubkey())
if err != nil { if err != nil {
t.Fatalf("failed to create PoL tx: %v", err) t.Fatalf("failed to create PoL tx: %v", err)
} }

View file

@ -207,7 +207,7 @@ func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]*simBlo
polTx, err := types.NewPoLTx( polTx, err := types.NewPoLTx(
sim.chainConfig.ChainID, sim.chainConfig.ChainID,
sim.chainConfig.Berachain.Prague1.PoLDistributorAddress, sim.chainConfig.Berachain.Prague1.PoLDistributorAddress,
new(big.Int).Sub(result.Number(), big.NewInt(1)), result.Number(),
params.PoLTxGasLimit, params.PoLTxGasLimit,
result.BaseFee(), result.BaseFee(),
result.ProposerPubkey(), result.ProposerPubkey(),

View file

@ -502,7 +502,7 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
tx, err := types.NewPoLTx( tx, err := types.NewPoLTx(
miner.chainConfig.ChainID, miner.chainConfig.ChainID,
miner.chainConfig.Berachain.Prague1.PoLDistributorAddress, miner.chainConfig.Berachain.Prague1.PoLDistributorAddress,
new(big.Int).Sub(env.header.Number, big.NewInt(1)), env.header.Number,
params.PoLTxGasLimit, params.PoLTxGasLimit,
env.header.BaseFee, env.header.BaseFee,
env.header.ParentProposerPubkey, env.header.ParentProposerPubkey,