diff --git a/go.mod b/go.mod index fcaaee2e..1c8f090a 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 - github.com/unicitynetwork/bft-go-base v1.1.0 + github.com/unicitynetwork/bft-go-base v1.1.1-0.20260421100318-01ab63a83bf5 go.etcd.io/bbolt v1.4.0 go.opentelemetry.io/otel v1.32.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 diff --git a/go.sum b/go.sum index 99505aaf..0e0dd665 100644 --- a/go.sum +++ b/go.sum @@ -462,8 +462,8 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/unicitynetwork/bft-go-base v1.1.0 h1:x1+kX0X+n4CmNibBs0f8oWwoZ5UCW40Gaq6WYhUcUZQ= -github.com/unicitynetwork/bft-go-base v1.1.0/go.mod h1:hBnOG52VRy/vpgIBUulTgk7PBTwODZ2xkVjCEu5yRcQ= +github.com/unicitynetwork/bft-go-base v1.1.1-0.20260421100318-01ab63a83bf5 h1:+HcpaSvDTGBiqis5noCph0Qu/QuDjoccrlDr0q/BxII= +github.com/unicitynetwork/bft-go-base v1.1.1-0.20260421100318-01ab63a83bf5/go.mod h1:hBnOG52VRy/vpgIBUulTgk7PBTwODZ2xkVjCEu5yRcQ= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= diff --git a/keyvaluedb/boltdb/bolt_db_test.go b/keyvaluedb/boltdb/bolt_db_test.go index 9852e766..87049182 100644 --- a/keyvaluedb/boltdb/bolt_db_test.go +++ b/keyvaluedb/boltdb/bolt_db_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "github.com/unicitynetwork/bft-core/keyvaluedb" ) @@ -40,10 +41,11 @@ func initBoltDB(t *testing.T) *BoltDB { boltDB, err := New(filepath.Join(dbDir, "bolt.db")) require.NoError(t, err) require.NotNil(t, boltDB) + t.Cleanup(func() { boltDB.Close() }) return boltDB } -func TestMemDB_TestIsEmpty(t *testing.T) { +func TestBoltDB_TestIsEmpty(t *testing.T) { db := initBoltDB(t) require.NotNil(t, db) empty, err := keyvaluedb.IsEmpty(db) diff --git a/keyvaluedb/boltdb/iterator_test.go b/keyvaluedb/boltdb/iterator_test.go index 878d3510..27a63a23 100644 --- a/keyvaluedb/boltdb/iterator_test.go +++ b/keyvaluedb/boltdb/iterator_test.go @@ -19,6 +19,7 @@ func initDB(t *testing.T, defaults []string) *BoltDB { boltDB, err := New(filepath.Join(dir, "bolt.db")) require.NoError(t, err) require.NotNil(t, boltDB) + t.Cleanup(func() { boltDB.Close() }) if defaults == nil { return boltDB } diff --git a/network/network_test.go b/network/network_test.go index e32a69f1..391476d3 100644 --- a/network/network_test.go +++ b/network/network_test.go @@ -406,7 +406,7 @@ func Test_LibP2PNetwork_sendMsg(t *testing.T) { defer cancel() err = sendMsg(ctx, nw1.self, "test/p", msg, peer2.ID()) require.ErrorContains(t, err, fmt.Sprintf("open p2p stream: failed to dial: failed to dial %s: all dials failed", peer2.ID())) - require.ErrorContains(t, err, `connection refused`) + require.Regexp(t, "(connection refused|actively refused it)", err.Error()) }) t.Run("context cancelled", func(t *testing.T) { diff --git a/network/protocol/abdrc/recovery.go b/network/protocol/abdrc/recovery.go index e624621e..02648274 100644 --- a/network/protocol/abdrc/recovery.go +++ b/network/protocol/abdrc/recovery.go @@ -7,9 +7,10 @@ import ( "slices" "time" + "github.com/unicitynetwork/bft-go-base/types" + "github.com/unicitynetwork/bft-core/network/protocol/certification" rctypes "github.com/unicitynetwork/bft-core/rootchain/consensus/types" - "github.com/unicitynetwork/bft-go-base/types" ) type StateRequestMsg struct { @@ -174,7 +175,7 @@ func (si *ShardInfo) IsValid() error { } if si.UC != nil { - if err := si.UC.IsValid(si.Partition, si.ShardConfHash); err != nil { + if err := si.UC.IsValid(si.Partition, si.Shard, si.ShardConfHash); err != nil { return fmt.Errorf("invalid UC: %w", err) } if err := si.TR.IsValid(); err != nil { diff --git a/rootchain/consensus/storage/block_store_test.go b/rootchain/consensus/storage/block_store_test.go index 9ae7c3d9..6a3726ce 100644 --- a/rootchain/consensus/storage/block_store_test.go +++ b/rootchain/consensus/storage/block_store_test.go @@ -329,6 +329,7 @@ func Test_BlockStore_persistence(t *testing.T) { require.NoError(t, db.Close()) db, err = NewBoltStorage(dbPath) require.NoError(t, err) + t.Cleanup(func() { db.Close() }) // to make sure we load the state from db send in empty genesis record storeB, err := New(crypto.SHA256, db, orchestration, log) diff --git a/rootchain/consensus/storage/db_bolt_test.go b/rootchain/consensus/storage/db_bolt_test.go index 82b8d31e..3cebbc4b 100644 --- a/rootchain/consensus/storage/db_bolt_test.go +++ b/rootchain/consensus/storage/db_bolt_test.go @@ -344,6 +344,7 @@ func Test_BoltDB_SafetyModule_API(t *testing.T) { require.NoError(t, db.Close()) db, err = NewBoltStorage(dbName) require.NoError(t, err) + t.Cleanup(func() { db.Close() }) require.EqualValues(t, 21, db.GetHighestQcRound()) require.EqualValues(t, 22, db.GetHighestVotedRound()) diff --git a/rootchain/consensus/types/proposal_block.go b/rootchain/consensus/types/proposal_block.go index 7b4fde37..fada7b5d 100644 --- a/rootchain/consensus/types/proposal_block.go +++ b/rootchain/consensus/types/proposal_block.go @@ -35,8 +35,8 @@ type Payload struct { } func (x *Payload) IsValid() error { - // there can only be one request per partition identifier in a block - sysIdSet := map[types.PartitionID]struct{}{} + // there can only be one request per partition shard in a block + sysIdSet := map[types.PartitionShardID]struct{}{} for _, req := range x.Requests { if err := req.IsValid(); err != nil { @@ -46,10 +46,11 @@ func (x *Payload) IsValid() error { if req.CertReason == T2Timeout && len(req.Requests) > 0 { return fmt.Errorf("partition %s timeout proof contains requests", req.Partition) } - if _, found := sysIdSet[req.Partition]; found { - return fmt.Errorf("duplicate requests for partition %s", req.Partition) + key := types.PartitionShardID{PartitionID: req.Partition, ShardID: req.Shard.Key()} + if _, found := sysIdSet[key]; found { + return fmt.Errorf("duplicate requests for partition %s shard %s", req.Partition, req.Shard) } - sysIdSet[req.Partition] = struct{}{} + sysIdSet[key] = struct{}{} } return nil } diff --git a/rootchain/consensus/types/proposal_block_test.go b/rootchain/consensus/types/proposal_block_test.go index f1f9ee5b..e45fd63f 100644 --- a/rootchain/consensus/types/proposal_block_test.go +++ b/rootchain/consensus/types/proposal_block_test.go @@ -167,6 +167,7 @@ func TestPayload_IsValid(t *testing.T) { type fields struct { Requests []*IRChangeReq } + s0, s1 := types.ShardID{}.Split() tests := []struct { name string fields fields @@ -189,6 +190,22 @@ func TestPayload_IsValid(t *testing.T) { }}, wantErrStr: "", }, + { + name: "duplicate partition different shard", + fields: fields{Requests: []*IRChangeReq{ + {Partition: 1, Shard: s0, CertReason: T2Timeout}, + {Partition: 1, Shard: s1, CertReason: T2Timeout}, + }}, + wantErrStr: "", + }, + { + name: "duplicate partition same shard", + fields: fields{Requests: []*IRChangeReq{ + {Partition: 1, Shard: s0, CertReason: T2Timeout}, + {Partition: 1, Shard: s0, CertReason: T2Timeout}, + }}, + wantErrStr: "duplicate requests for partition 00000001 shard 0", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {