mirror of
https://github.com/luxfi/bft.git
synced 2026-10-30 17:01:54 +00:00
Reapplies the fork's whole delta on top of the merge, as one reviewable diff rather than 43 conflict resolutions. Nothing here changes consensus behaviour. - module github.com/luxfi/bft, Go 1.26.4; root package simplex -> bft, which would otherwise collide with the simplex/ subpackage under this module name. - go.uber.org/zap -> github.com/luxfi/log, so common.Logger takes ...log.Field. zap.Error maps to log.Err: log.Error is luxfi/log's package-level logging function, not a field constructor, and the compiler is the only thing that catches that. Needs luxfi/log v1.6.1 for the Stringers constructor. - avalanchego/ -> host/. The package holds NodeID, VMBlock, Bitmask and size limits — the host node's types, vendored to avoid importing a whole node — so it is named for what it holds. Renaming it luxd/ would have swapped one brand for another and said just as little. - testutil/logger.go reimplemented without zapcore. Upstream layers a keyword-filtering Core, a debug-swallowing Encoder and a Tee because that is zap's extension model; luxfi/log has no such seam, so every policy is applied in one emit. That also fixes two defects the layering caused: SilenceExceptKeywords rebuilt the logger and discarded an installed Intercept hook, and the two sinks read different env vars (LOG_LEVEL vs log_level) so they disagreed about suppressing debug. Hooks run outside the lock, so a hook that logs fails the test instead of deadlocking it. Fatal panics rather than exiting, because exiting takes the suite down with no attribution. - simplex/monitor_test.go keeps a local logger: testutil imports simplex, so an internal test cannot import testutil back without closing a cycle. - README keeps the name Simplex throughout — it is the protocol's own name and the subject of reference [1]. Only the deployment target changed. The HyperSDK sentence still says Avalanche because that sentence is true. - Drops the fork's Makefile: it duplicated unit-tests.sh and fuzz.sh, and ran the suite with -timeout 30s when simplex alone needs over 100s. Co-authored-by: Hanzo Dev <[email protected]>
182 lines
4.8 KiB
Go
182 lines
4.8 KiB
Go
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package random_network
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/luxfi/bft/common"
|
|
"github.com/luxfi/bft/testutil"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var emptyBlacklist = common.Blacklist{
|
|
NodeCount: 4,
|
|
SuspectedNodes: common.SuspectedNodes{},
|
|
Updates: []common.BlacklistUpdate{},
|
|
}
|
|
|
|
func TestMempoolVerifiesTx(t *testing.T) {
|
|
logger := testutil.MakeLogger(t, 1)
|
|
logger.Silence() // so we dont log errors/warns
|
|
|
|
ctx := context.Background()
|
|
require := require.New(t)
|
|
round0MD := NewProtocolMetadata(0, 0, common.Digest{})
|
|
config := DefaultFuzzConfig()
|
|
|
|
tests := []struct {
|
|
name string
|
|
expectErr error
|
|
setup func() (*Mempool, *Block, error)
|
|
}{
|
|
{
|
|
name: "ValidTx",
|
|
expectErr: nil,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx := CreateNewTX()
|
|
mempool.AddPendingTXs(tx)
|
|
|
|
block := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx})
|
|
|
|
return mempool, block, nil
|
|
},
|
|
},
|
|
{
|
|
name: "Duplicate Tx In Block",
|
|
expectErr: errDuplicateTxInBlock,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx := CreateNewTX()
|
|
mempool.AddPendingTXs(tx)
|
|
|
|
block := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx, tx})
|
|
return mempool, block, nil
|
|
},
|
|
},
|
|
{
|
|
name: "Already Accepted",
|
|
expectErr: errDoubleBlockVerification,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx := CreateNewTX()
|
|
mempool.AddPendingTXs(tx)
|
|
|
|
block := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx})
|
|
mempool.AcceptBlock(block)
|
|
|
|
mempool.AddPendingTXs(tx)
|
|
return mempool, block, nil
|
|
},
|
|
},
|
|
{
|
|
name: "Already In Chain",
|
|
expectErr: errAlreadyInChain,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx := CreateNewTX()
|
|
mempool.AddPendingTXs(tx)
|
|
|
|
parentBlock := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx})
|
|
if err := mempool.VerifyBlock(ctx, parentBlock); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
mempool.AddPendingTXs(tx)
|
|
md := NewProtocolMetadata(1, 1, parentBlock.digest)
|
|
block := NewBlock(md, emptyBlacklist, mempool, []*TX{tx})
|
|
return mempool, block, nil
|
|
},
|
|
},
|
|
{
|
|
name: "Tx Verification Fails",
|
|
expectErr: errTxVerification,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx := CreateNewTX()
|
|
tx.SetShouldFailVerification()
|
|
mempool.AddPendingTXs(tx)
|
|
|
|
block := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx})
|
|
|
|
return mempool, block, nil
|
|
},
|
|
},
|
|
{
|
|
name: "Correctly verifies transaction not in chain",
|
|
expectErr: nil,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx1 := CreateNewTX()
|
|
mempool.AddPendingTXs(tx1)
|
|
|
|
blockWithSameTxButNotParent := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx1})
|
|
err := mempool.VerifyBlock(ctx, blockWithSameTxButNotParent)
|
|
|
|
mempool.AddPendingTXs(tx1)
|
|
block := NewBlock(NewProtocolMetadata(1, 1, common.Digest{}), emptyBlacklist, mempool, []*TX{tx1})
|
|
return mempool, block, err
|
|
},
|
|
},
|
|
{
|
|
name: "Double Block Verification",
|
|
expectErr: errDoubleBlockVerification,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx := CreateNewTX()
|
|
mempool.AddPendingTXs(tx)
|
|
|
|
block := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx})
|
|
err := mempool.VerifyBlock(ctx, block)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
mempool.AddPendingTXs(tx)
|
|
return mempool, block, nil
|
|
},
|
|
},
|
|
{
|
|
name: "Parent Previously Verified But Was Pruned",
|
|
expectErr: errParentNotFound,
|
|
setup: func() (*Mempool, *Block, error) {
|
|
mempool := NewMempool(logger, config)
|
|
tx1 := CreateNewTX()
|
|
tx2 := CreateNewTX()
|
|
childTx := CreateNewTX()
|
|
mempool.AddPendingTXs(tx1)
|
|
mempool.AddPendingTXs(tx2)
|
|
|
|
// create & verify two siblings
|
|
brother := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx1})
|
|
if err := mempool.VerifyBlock(ctx, brother); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
sister := NewBlock(round0MD, emptyBlacklist, mempool, []*TX{tx2})
|
|
if err := mempool.VerifyBlock(ctx, sister); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// accept the sister, so the brother should be pruned
|
|
mempool.AcceptBlock(sister)
|
|
|
|
childBlock := NewBlock(NewProtocolMetadata(1, 1, brother.digest), emptyBlacklist, mempool, []*TX{childTx})
|
|
return mempool, childBlock, nil
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mempool, block, err := tt.setup()
|
|
require.NoError(err)
|
|
err = mempool.VerifyBlock(ctx, block)
|
|
require.ErrorIs(err, tt.expectErr)
|
|
})
|
|
}
|
|
}
|