feat(consensus): full block validation orchestrator
ValidateBlock combines timestamp, miner tx, and reward checks into a single entry point for block-level consensus validation. Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
parent
83a715cdb8
commit
7abac5e011
2 changed files with 73 additions and 0 deletions
|
|
@ -124,3 +124,28 @@ func ValidateBlockReward(minerTx *types.Transaction, height, blockSize, medianSi
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateBlock performs full consensus validation on a block. It checks
|
||||
// the timestamp, miner transaction structure, and reward. Transaction
|
||||
// semantic validation for regular transactions should be done separately
|
||||
// via ValidateTransaction for each tx in the block.
|
||||
func ValidateBlock(blk *types.Block, height, blockSize, medianSize, totalFees, adjustedTime uint64,
|
||||
recentTimestamps []uint64, forks []config.HardFork) error {
|
||||
|
||||
// Timestamp validation.
|
||||
if err := CheckTimestamp(blk.Timestamp, blk.Flags, adjustedTime, recentTimestamps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Miner transaction structure.
|
||||
if err := ValidateMinerTx(&blk.MinerTx, height, forks); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Block reward.
|
||||
if err := ValidateBlockReward(&blk.MinerTx, height, blockSize, medianSize, totalFees, forks); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,3 +150,51 @@ func TestValidateBlockReward_Good_WithFees(t *testing.T) {
|
|||
err := ValidateBlockReward(tx, height, 1000, config.BlockGrantedFullRewardZone, fees, config.MainnetForks)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidateBlock_Good(t *testing.T) {
|
||||
now := uint64(time.Now().Unix())
|
||||
height := uint64(100)
|
||||
blk := &types.Block{
|
||||
BlockHeader: types.BlockHeader{
|
||||
MajorVersion: 1,
|
||||
Timestamp: now,
|
||||
Flags: 0, // PoW
|
||||
},
|
||||
MinerTx: *validMinerTx(height),
|
||||
}
|
||||
|
||||
err := ValidateBlock(blk, height, 1000, config.BlockGrantedFullRewardZone, 0, now, nil, config.MainnetForks)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidateBlock_Bad_Timestamp(t *testing.T) {
|
||||
now := uint64(time.Now().Unix())
|
||||
height := uint64(100)
|
||||
blk := &types.Block{
|
||||
BlockHeader: types.BlockHeader{
|
||||
MajorVersion: 1,
|
||||
Timestamp: now + config.BlockFutureTimeLimit + 100,
|
||||
Flags: 0,
|
||||
},
|
||||
MinerTx: *validMinerTx(height),
|
||||
}
|
||||
|
||||
err := ValidateBlock(blk, height, 1000, config.BlockGrantedFullRewardZone, 0, now, nil, config.MainnetForks)
|
||||
assert.ErrorIs(t, err, ErrTimestampFuture)
|
||||
}
|
||||
|
||||
func TestValidateBlock_Bad_MinerTx(t *testing.T) {
|
||||
now := uint64(time.Now().Unix())
|
||||
height := uint64(100)
|
||||
blk := &types.Block{
|
||||
BlockHeader: types.BlockHeader{
|
||||
MajorVersion: 1,
|
||||
Timestamp: now,
|
||||
Flags: 0,
|
||||
},
|
||||
MinerTx: *validMinerTx(200), // wrong height
|
||||
}
|
||||
|
||||
err := ValidateBlock(blk, height, 1000, config.BlockGrantedFullRewardZone, 0, now, nil, config.MainnetForks)
|
||||
assert.ErrorIs(t, err, ErrMinerTxHeight)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue