github.com/ethersphere/bee/v2@v2.2.0/pkg/soc/validator_test.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package soc_test
     6  
     7  import (
     8  	"crypto/rand"
     9  	"io"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/ethersphere/bee/v2/pkg/cac"
    14  	"github.com/ethersphere/bee/v2/pkg/crypto"
    15  	"github.com/ethersphere/bee/v2/pkg/soc"
    16  	"github.com/ethersphere/bee/v2/pkg/swarm"
    17  )
    18  
    19  // TestValid verifies that the validator can detect
    20  // valid soc chunks.
    21  func TestValid(t *testing.T) {
    22  	t.Parallel()
    23  
    24  	socAddress := swarm.MustParseHexAddress("9d453ebb73b2fedaaf44ceddcf7a0aa37f3e3d6453fea5841c31f0ea6d61dc85")
    25  
    26  	// signed soc chunk of:
    27  	// id: 0
    28  	// wrapped chunk of: `foo`
    29  	// owner: 0x8d3766440f0d7b949a5e32995d09619a7f86e632
    30  	sch := swarm.NewChunk(socAddress, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 205, 56, 79, 235, 193, 51, 183, 178, 69, 229, 221, 198, 45, 130, 210, 205, 237, 145, 130, 210, 113, 97, 38, 205, 136, 68, 80, 154, 246, 90, 5, 61, 235, 65, 130, 8, 2, 127, 84, 142, 62, 136, 52, 58, 246, 248, 74, 135, 114, 251, 60, 235, 192, 161, 131, 58, 14, 167, 236, 12, 19, 72, 49, 27, 3, 0, 0, 0, 0, 0, 0, 0, 102, 111, 111})
    31  
    32  	// check valid chunk
    33  	if !soc.Valid(sch) {
    34  		t.Fatal("valid chunk evaluates to invalid")
    35  	}
    36  }
    37  
    38  // TestValidDispersedReplica verifies that the validator can detect
    39  // valid dispersed replicas chunks.
    40  func TestValidDispersedReplica(t *testing.T) {
    41  	t.Parallel()
    42  
    43  	t.Run("valid", func(t *testing.T) {
    44  		privKey, _ := crypto.DecodeSecp256k1PrivateKey(append([]byte{1}, make([]byte, 31)...))
    45  		signer := crypto.NewDefaultSigner(privKey)
    46  
    47  		chData := make([]byte, swarm.ChunkSize)
    48  		_, _ = io.ReadFull(rand.Reader, chData)
    49  		ch, err := cac.New(chData)
    50  		if err != nil {
    51  			t.Fatal(err)
    52  		}
    53  		id := append([]byte{1}, ch.Address().Bytes()[1:]...)
    54  
    55  		socCh, err := soc.New(id, ch).Sign(signer)
    56  		if err != nil {
    57  			t.Fatal(err)
    58  		}
    59  
    60  		// check valid chunk
    61  		if !soc.Valid(socCh) {
    62  			t.Fatal("dispersed replica chunk is invalid")
    63  		}
    64  	})
    65  
    66  	t.Run("invalid", func(t *testing.T) {
    67  		privKey, _ := crypto.DecodeSecp256k1PrivateKey(append([]byte{1}, make([]byte, 31)...))
    68  		signer := crypto.NewDefaultSigner(privKey)
    69  
    70  		chData := make([]byte, swarm.ChunkSize)
    71  		_, _ = io.ReadFull(rand.Reader, chData)
    72  		ch, err := cac.New(chData)
    73  		if err != nil {
    74  			t.Fatal(err)
    75  		}
    76  		id := append([]byte{1}, ch.Address().Bytes()[1:]...)
    77  		// change to invalid ID
    78  		id[2] += 1
    79  
    80  		socCh, err := soc.New(id, ch).Sign(signer)
    81  		if err != nil {
    82  			t.Fatal(err)
    83  		}
    84  
    85  		// check valid chunk
    86  		if soc.Valid(socCh) {
    87  			t.Fatal("dispersed replica should be invalid")
    88  		}
    89  	})
    90  }
    91  
    92  // TestInvalid verifies that the validator can detect chunks
    93  // with invalid data and invalid address.
    94  func TestInvalid(t *testing.T) {
    95  	t.Parallel()
    96  
    97  	socAddress := swarm.MustParseHexAddress("9d453ebb73b2fedaaf44ceddcf7a0aa37f3e3d6453fea5841c31f0ea6d61dc85")
    98  	// signed soc chunk of:
    99  	// id: 0
   100  	// wrapped chunk of: `foo`
   101  	// owner: 0x8d3766440f0d7b949a5e32995d09619a7f86e632
   102  
   103  	makeSocData := func() []byte {
   104  		return []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 205, 56, 79, 235, 193, 51, 183, 178, 69, 229, 221, 198, 45, 130, 210, 205, 237, 145, 130, 210, 113, 97, 38, 205, 136, 68, 80, 154, 246, 90, 5, 61, 235, 65, 130, 8, 2, 127, 84, 142, 62, 136, 52, 58, 246, 248, 74, 135, 114, 251, 60, 235, 192, 161, 131, 58, 14, 167, 236, 12, 19, 72, 49, 27, 3, 0, 0, 0, 0, 0, 0, 0, 102, 111, 111}
   105  	}
   106  
   107  	for _, c := range []struct {
   108  		name  string
   109  		chunk func() swarm.Chunk
   110  	}{
   111  		{
   112  			name: "wrong soc address",
   113  			chunk: func() swarm.Chunk {
   114  				wrongAddressBytes := socAddress.Clone().Bytes()
   115  				wrongAddressBytes[0] = 255 - wrongAddressBytes[0]
   116  				wrongAddress := swarm.NewAddress(wrongAddressBytes)
   117  				data := makeSocData()
   118  				return swarm.NewChunk(wrongAddress, data)
   119  			},
   120  		},
   121  		{
   122  			name: "invalid data",
   123  			chunk: func() swarm.Chunk {
   124  				addr := socAddress.Clone()
   125  				data := makeSocData()
   126  				cursor := swarm.HashSize + swarm.SocSignatureSize
   127  				chunkData := data[cursor:]
   128  				chunkData[0] = 0x01
   129  				return swarm.NewChunk(addr, data)
   130  			},
   131  		},
   132  		{
   133  			name: "invalid id",
   134  			chunk: func() swarm.Chunk {
   135  				addr := socAddress.Clone()
   136  				data := makeSocData()
   137  				id := data[:swarm.HashSize]
   138  				id[0] = 0x01
   139  				return swarm.NewChunk(addr, data)
   140  			},
   141  		},
   142  		{
   143  			name: "invalid signature",
   144  			chunk: func() swarm.Chunk {
   145  				addr := socAddress.Clone()
   146  				data := makeSocData()
   147  				// modify signature
   148  				cursor := swarm.HashSize + swarm.SocSignatureSize
   149  				sig := data[swarm.HashSize:cursor]
   150  				sig[0] = 0x01
   151  				return swarm.NewChunk(addr, data)
   152  			},
   153  		},
   154  		{
   155  			name: "nil data",
   156  			chunk: func() swarm.Chunk {
   157  				addr := socAddress.Clone()
   158  				return swarm.NewChunk(addr, nil)
   159  			},
   160  		},
   161  		{
   162  			name: "small data",
   163  			chunk: func() swarm.Chunk {
   164  				addr := socAddress.Clone()
   165  				return swarm.NewChunk(addr, []byte("small"))
   166  			},
   167  		},
   168  		{
   169  			name: "large data",
   170  			chunk: func() swarm.Chunk {
   171  				addr := socAddress.Clone()
   172  				return swarm.NewChunk(addr, []byte(strings.Repeat("a", swarm.ChunkSize+swarm.SpanSize+1)))
   173  			},
   174  		},
   175  	} {
   176  		c := c
   177  		t.Run(c.name, func(t *testing.T) {
   178  			t.Parallel()
   179  
   180  			if soc.Valid(c.chunk()) {
   181  				t.Fatal("chunk with invalid data evaluates to valid")
   182  			}
   183  		})
   184  	}
   185  }