Skip to content

Commit

Permalink
dsmr: verify chunk producer was supposed to produce the given chunk (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
tsachiherman authored Jan 24, 2025
1 parent 49cbe48 commit 606db62
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 56 deletions.
180 changes: 144 additions & 36 deletions x/dsmr/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (

const (
networkID = uint32(123)
testingDefaultValidityWindowDuration = time.Duration(5)
testingDefaultValidityWindowDuration = 5 * time.Second
)

var (
Expand Down Expand Up @@ -435,33 +435,114 @@ func TestNode_AcceptedChunksAvailableOverGetChunk(t *testing.T) {

// Node should be willing to sign valid chunks
func TestNode_GetChunkSignature_SignValidChunk(t *testing.T) {
nodeID := ids.GenerateTestNodeID()
sk, err := bls.NewSecretKey()
require.NoError(t, err)
pk := bls.PublicFromSecretKey(sk)
tests := []struct {
name string
verifier Verifier[dsmrtest.Tx]
wantErr error
name string
verifier Verifier[dsmrtest.Tx]
producerNode ids.NodeID
wantErr error
nodeLastAcceptedTimestamp int64
chunkExpiry int64
}{
{
name: "invalid chunk",
verifier: failVerifier{},
wantErr: ErrInvalidChunk,
name: "invalid chunk",
verifier: failVerifier{},
wantErr: ErrInvalidChunk,
producerNode: ids.GenerateTestNodeID(),
nodeLastAcceptedTimestamp: 1,
chunkExpiry: 123,
},
{
name: "valid chunk",
verifier: ChunkVerifier[dsmrtest.Tx]{
networkID: networkID,
chainID: chainID,
},
name: "invalid chunk ( bad producer id )",
verifier: NewChunkVerifier[dsmrtest.Tx](
networkID,
chainID,
pChain{
validators: []Validator{{
NodeID: nodeID,
Weight: 1,
PublicKey: pk,
}},
},
1,
1,
testingDefaultValidityWindowDuration,
),
wantErr: ErrInvalidChunk,
producerNode: ids.GenerateTestNodeID(),
nodeLastAcceptedTimestamp: 1,
chunkExpiry: 123,
},
{
name: "invalid chunk ( chunk timestamp too old )",
verifier: NewChunkVerifier[dsmrtest.Tx](
networkID,
chainID,
pChain{
validators: []Validator{{
NodeID: nodeID,
Weight: 1,
PublicKey: pk,
}},
},
1,
1,
testingDefaultValidityWindowDuration,
),
wantErr: ErrInvalidChunk,
producerNode: nodeID,
nodeLastAcceptedTimestamp: 5000,
chunkExpiry: 123,
},
{
name: "invalid chunk ( chunk timestamp too into the future )",
verifier: NewChunkVerifier[dsmrtest.Tx](
networkID,
chainID,
pChain{
validators: []Validator{{
NodeID: nodeID,
Weight: 1,
PublicKey: pk,
}},
},
1,
1,
testingDefaultValidityWindowDuration,
),
wantErr: ErrInvalidChunk,
producerNode: nodeID,
nodeLastAcceptedTimestamp: 1,
chunkExpiry: 1 + int64(testingDefaultValidityWindowDuration),
},
{
name: "valid chunk",
producerNode: nodeID,
verifier: NewChunkVerifier[dsmrtest.Tx](
networkID,
chainID,
pChain{
validators: []Validator{{
NodeID: nodeID,
Weight: 1,
PublicKey: pk,
}},
},
1,
1,
testingDefaultValidityWindowDuration,
),
nodeLastAcceptedTimestamp: 1,
chunkExpiry: 123,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := require.New(t)

nodeID := ids.GenerateTestNodeID()
sk, err := bls.NewSecretKey()
r.NoError(err)
pk := bls.PublicFromSecretKey(sk)
signer := warp.NewSigner(sk, networkID, chainID)

validators := []Validator{
Expand Down Expand Up @@ -526,10 +607,23 @@ func TestNode_GetChunkSignature_SignValidChunk(t *testing.T) {
)
r.NoError(err)

r.NoError(node.BuildChunk(context.Background(), []dsmrtest.Tx{
{
ID: ids.GenerateTestID(),
Expiry: 456,
Sponsor: codec.Address{4, 5, 6},
},
}, tt.nodeLastAcceptedTimestamp, codec.Address{123}))

blk, err := node.BuildBlock(context.Background(), node.LastAccepted, tt.nodeLastAcceptedTimestamp)
r.NoError(err)
_, err = node.Accept(context.Background(), blk)
r.NoError(err)

unsignedChunk := UnsignedChunk[dsmrtest.Tx]{
Producer: ids.GenerateTestNodeID(),
Producer: tt.producerNode,
Beneficiary: codec.Address{123},
Expiry: 123,
Expiry: tt.chunkExpiry,
Txs: []dsmrtest.Tx{
{
ID: ids.GenerateTestID(),
Expand Down Expand Up @@ -1266,10 +1360,16 @@ func Test_Verify_BadBlock(t *testing.T) {

type failVerifier struct{}

func (failVerifier) SetMin(int64) {}

func (failVerifier) Verify(Chunk[dsmrtest.Tx]) error {
return errors.New("fail")
}

func (failVerifier) VerifyCertificate(context.Context, *ChunkCertificate) error {
return errors.New("fail")
}

type testNode struct {
ChunkStorage *ChunkStorage[dsmrtest.Tx]
GetChunkHandler p2p.Handler
Expand All @@ -1284,25 +1384,39 @@ func newTestNode(t *testing.T) *Node[dsmrtest.Tx] {

func newTestNodes(t *testing.T, n int) []*Node[dsmrtest.Tx] {
nodes := make([]testNode, 0, n)
validators := make([]Validator, 0, n)
validators := make([]Validator, n)
secretKeys := make([]*bls.SecretKey, n)
var err error
for i := 0; i < n; i++ {
sk, err := bls.NewSecretKey()
secretKeys[i], err = bls.NewSecretKey()
require.NoError(t, err)
pk := bls.PublicFromSecretKey(sk)
signer := warp.NewSigner(sk, networkID, chainID)
verifier := ChunkVerifier[dsmrtest.Tx]{networkID: networkID, chainID: chainID}
pk := bls.PublicFromSecretKey(secretKeys[i])
validators[i] = Validator{
NodeID: ids.GenerateTestNodeID(),
Weight: 1,
PublicKey: pk,
}
}

for i := 0; i < n; i++ {
signer := warp.NewSigner(secretKeys[i], networkID, chainID)
verifier := NewChunkVerifier[dsmrtest.Tx](
networkID,
chainID,
pChain{validators: validators},
1,
1,
testingDefaultValidityWindowDuration,
)
chunkStorage, err := NewChunkStorage[dsmrtest.Tx](verifier, memdb.New())
require.NoError(t, err)

getChunkHandler := &GetChunkHandler[dsmrtest.Tx]{
storage: chunkStorage,
}
chunkSignatureRequestHandler := acp118.NewHandler(ChunkSignatureRequestVerifier[dsmrtest.Tx]{
verifier: ChunkVerifier[dsmrtest.Tx]{
networkID: networkID,
chainID: chainID,
},
storage: chunkStorage,
verifier: verifier,
storage: chunkStorage,
}, signer)
chunkCertificateGossipHandler := ChunkCertificateGossipHandler[dsmrtest.Tx]{
storage: chunkStorage,
Expand All @@ -1313,13 +1427,7 @@ func newTestNodes(t *testing.T, n int) []*Node[dsmrtest.Tx] {
GetChunkHandler: getChunkHandler,
ChunkSignatureRequestHandler: chunkSignatureRequestHandler,
ChunkCertificateGossipHandler: chunkCertificateGossipHandler,
Sk: sk,
})

validators = append(validators, Validator{
NodeID: ids.GenerateTestNodeID(),
Weight: 1,
PublicKey: pk,
Sk: secretKeys[i],
})
}

Expand Down
4 changes: 2 additions & 2 deletions x/dsmr/p2p.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ type ChunkCertificateGossipHandler[T Tx] struct {
}

// TODO error handling + logs
func (c ChunkCertificateGossipHandler[T]) AppGossip(_ context.Context, _ ids.NodeID, gossipBytes []byte) {
func (c ChunkCertificateGossipHandler[T]) AppGossip(ctx context.Context, _ ids.NodeID, gossipBytes []byte) {
gossip := &dsmr.ChunkCertificateGossip{}
if err := proto.Unmarshal(gossipBytes, gossip); err != nil {
return
Expand All @@ -163,7 +163,7 @@ func (c ChunkCertificateGossipHandler[T]) AppGossip(_ context.Context, _ ids.Nod
return
}

if err := c.storage.SetChunkCert(chunkCert.ChunkID, &chunkCert); err != nil {
if err := c.storage.SetChunkCert(ctx, chunkCert.ChunkID, &chunkCert); err != nil {
return
}
}
Expand Down
Loading

0 comments on commit 606db62

Please sign in to comment.