148 lines
4.4 KiB
Go
148 lines
4.4 KiB
Go
// Copyright (c) 2017-2026 Lethean (https://lt.hn)
|
|
//
|
|
// Licensed under the European Union Public Licence (EUPL) version 1.2.
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
//go:build !integration
|
|
|
|
package consensus
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"dappco.re/go/core/blockchain/config"
|
|
"dappco.re/go/core/blockchain/types"
|
|
)
|
|
|
|
// validV2Tx returns a minimal valid v2 (Zarcanum) transaction for testing.
|
|
func validV2Tx() *types.Transaction {
|
|
return &types.Transaction{
|
|
Version: types.VersionPostHF4,
|
|
Vin: []types.TxInput{
|
|
types.TxInputZC{
|
|
KeyImage: types.KeyImage{1},
|
|
},
|
|
},
|
|
Vout: []types.TxOutput{
|
|
types.TxOutputZarcanum{StealthAddress: types.PublicKey{1}},
|
|
types.TxOutputZarcanum{StealthAddress: types.PublicKey{2}},
|
|
},
|
|
}
|
|
}
|
|
|
|
// validV3Tx returns a minimal valid v3 (HF5) transaction for testing.
|
|
func validV3Tx() *types.Transaction {
|
|
return &types.Transaction{
|
|
Version: types.VersionPostHF5,
|
|
HardforkID: 5,
|
|
Vin: []types.TxInput{
|
|
types.TxInputZC{
|
|
KeyImage: types.KeyImage{1},
|
|
},
|
|
},
|
|
Vout: []types.TxOutput{
|
|
types.TxOutputZarcanum{StealthAddress: types.PublicKey{1}},
|
|
types.TxOutputZarcanum{StealthAddress: types.PublicKey{2}},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestCheckTxVersion_Good(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
tx *types.Transaction
|
|
forks []config.HardFork
|
|
height uint64
|
|
}{
|
|
// v1 transaction before HF4 — valid.
|
|
{"v1_before_hf4", validV1Tx(), config.MainnetForks, 5000},
|
|
// v2 transaction after HF4, before HF5 — valid.
|
|
{"v2_after_hf4_before_hf5", validV2Tx(), config.TestnetForks, 150},
|
|
// v3 transaction after HF5 — valid.
|
|
{"v3_after_hf5", validV3Tx(), config.TestnetForks, 250},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := checkTxVersion(tt.tx, newTransactionForkState(tt.forks, tt.height), tt.height)
|
|
if err != nil {
|
|
t.Errorf("checkTxVersion returned unexpected error: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckTxVersion_Bad(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
tx *types.Transaction
|
|
forks []config.HardFork
|
|
height uint64
|
|
}{
|
|
// v0 regular transaction before HF4 — must still be v1.
|
|
{"v0_before_hf4", func() *types.Transaction {
|
|
tx := validV1Tx()
|
|
tx.Version = types.VersionInitial
|
|
return tx
|
|
}(), config.MainnetForks, 5000},
|
|
// v1 transaction after HF4 — must be v2.
|
|
{"v1_after_hf4", validV1Tx(), config.TestnetForks, 150},
|
|
// v2 transaction after HF5 — must be v3.
|
|
{"v2_after_hf5", validV2Tx(), config.TestnetForks, 250},
|
|
// v3 transaction after HF4 but before HF5 — too early.
|
|
{"v3_after_hf4_before_hf5", validV3Tx(), config.TestnetForks, 150},
|
|
// v3 transaction after HF5 with wrong hardfork id.
|
|
{"v3_after_hf5_wrong_hardfork", func() *types.Transaction {
|
|
tx := validV3Tx()
|
|
tx.HardforkID = 4
|
|
return tx
|
|
}(), config.TestnetForks, 250},
|
|
// v3 transaction before HF5 — too early.
|
|
{"v3_before_hf5", validV3Tx(), config.TestnetForks, 150},
|
|
// future version must be rejected.
|
|
{"v4_after_hf5", func() *types.Transaction {
|
|
tx := validV3Tx()
|
|
tx.Version = types.VersionPostHF5 + 1
|
|
return tx
|
|
}(), config.TestnetForks, 250},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := checkTxVersion(tt.tx, newTransactionForkState(tt.forks, tt.height), tt.height)
|
|
if err == nil {
|
|
t.Error("expected ErrTxVersionInvalid, got nil")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckTxVersion_Ugly(t *testing.T) {
|
|
// v2 at exact HF4 activation boundary (height 101 on testnet, HF4.Height=100).
|
|
txHF4 := validV2Tx()
|
|
err := checkTxVersion(txHF4, newTransactionForkState(config.TestnetForks, 101), 101)
|
|
if err != nil {
|
|
t.Errorf("v2 at HF4 activation boundary should be valid: %v", err)
|
|
}
|
|
|
|
// v1 at exact HF4 activation boundary should be rejected.
|
|
txPreHF4 := validV1Tx()
|
|
err = checkTxVersion(txPreHF4, newTransactionForkState(config.TestnetForks, 101), 101)
|
|
if err == nil {
|
|
t.Error("v1 at HF4 activation boundary should be rejected")
|
|
}
|
|
|
|
// v3 at exact HF5 activation boundary (height 201 on testnet, HF5.Height=200).
|
|
tx := validV3Tx()
|
|
err = checkTxVersion(tx, newTransactionForkState(config.TestnetForks, 201), 201)
|
|
if err != nil {
|
|
t.Errorf("v3 at HF5 activation boundary should be valid: %v", err)
|
|
}
|
|
|
|
// v2 at exact HF5 activation boundary — should be rejected.
|
|
tx2 := validV2Tx()
|
|
err = checkTxVersion(tx2, newTransactionForkState(config.TestnetForks, 201), 201)
|
|
if err == nil {
|
|
t.Error("v2 at HF5 activation boundary should be rejected")
|
|
}
|
|
}
|