package layer1 import ( "bytes" "testing" "github.com/number571/go-peer/pkg/crypto/hashing" "github.com/number571/go-peer/pkg/crypto/keybuilder" "github.com/number571/go-peer/pkg/crypto/puzzle" "github.com/number571/go-peer/pkg/crypto/random" "github.com/number571/go-peer/pkg/crypto/symmetric" "github.com/number571/go-peer/pkg/encoding" "github.com/number571/go-peer/pkg/payload" ) var ( _ payload.IPayload64 = &sInvalidPayload{} ) const ( tcWorkSize = 10 tcBody = "hello, world!" tcNetworkKey = "network_key_1" ) type sInvalidPayload struct{} func (p *sInvalidPayload) GetHead() uint64 { return 1 } func (p *sInvalidPayload) GetBody() []byte { return []byte{} } func (p *sInvalidPayload) ToBytes() []byte { return []byte{123} } func TestError(t *testing.T) { t.Parallel() str := "value" err := &SMessageError{str} if err.Error() != errPrefix+str { t.Fatal("incorrect err.Error()") } } func TestSettings(t *testing.T) { t.Parallel() for i := 0; i < 1; i++ { testSettings(t, i) } } func testSettings(t *testing.T, n int) { defer func() { if r := recover(); r == nil { t.Fatal("nothing panics") } }() switch n { // nolint: gocritic case 0: _ = NewConstructSettings(&SConstructSettings{}) } } func TestMessage(t *testing.T) { t.Parallel() sett := NewConstructSettings(&SConstructSettings{ FSettings: NewSettings(&SSettings{ FWorkSizeBits: tcWorkSize, FNetworkKey: tcNetworkKey, }), }) pld := []byte(tcBody) msgTmp := NewMessage(sett, pld) if !bytes.Equal(msgTmp.GetBody(), pld) { t.Fatal("payload body not equal body in message") } msg, err := LoadMessage(sett.GetSettings(), msgTmp.ToBytes()) if err != nil { t.Fatal(err) } if msgTmp.ToString() != msg.ToString() { t.Fatal("msgTmp != msg") } newHash := hashing.NewHasher(pld).ToBytes() if !bytes.Equal(msg.GetHash(), newHash) { t.Fatal("payload hash not equal hash of message") } keyBuilder := keybuilder.NewKeyBuilder(0, []byte{}) // the network_key must have good entropy key := keyBuilder.Build(tcNetworkKey, symmetric.CCipherKeySize) newHmac := hashing.NewHMACHasher(key, pld).ToBytes() if !bytes.Equal(msg.GetHmac(), newHmac) { t.Fatal("payload hmac not equal hmac of message") } newSett := NewConstructSettings(&SConstructSettings{ FSettings: NewSettings(&SSettings{ FWorkSizeBits: tcWorkSize, FNetworkKey: tcNetworkKey, }), }) for i := 0; i < 10; i++ { msgN := NewMessage(newSett, pld) if msgN.GetProof() == 0 { continue } msgL, err := LoadMessage(newSett.GetSettings(), msgN.ToBytes()) if err != nil { t.Fatal(err) } if msgN.GetProof() != msgL.GetProof() { t.Fatal("got invalid proof") } if len(msgN.ToBytes()) != len(msgL.ToBytes()) { t.Fatal("new msg size != load msg size") } if len(msgN.ToBytes()) != CMessageHeadSize+len(pld) { t.Fatal("msg size != head size + payload body") } break } msg1, err := LoadMessage(sett.GetSettings(), msg.ToBytes()) if err != nil { t.Fatal(err) } if !bytes.Equal(msg.GetBody(), msg1.GetBody()) { t.Fatal("load message not equal new message") } msg2, err := LoadMessage(sett.GetSettings(), msg.ToString()) if err != nil { t.Fatal(err) } if !bytes.Equal(msg.GetBody(), msg2.GetBody()) { t.Fatal("load message not equal new message") } msg3 := NewMessage(sett, pld).(*sMessage) msg3.fEncd[0] ^= 1 if _, err := LoadMessage(sett.GetSettings(), msg3.ToBytes()); err == nil { t.Fatal("success load with invalid encd") } if _, err := LoadMessage(sett.GetSettings(), struct{}{}); err == nil { t.Fatal("success load with unknown type of message") } if _, err := LoadMessage(sett.GetSettings(), []byte{1}); err == nil { t.Fatal("success load incorrect message") } if _, err := LoadMessage(sett.GetSettings(), []byte{1}); err == nil { t.Fatal("success load incorrect message") } randBytes := random.NewRandom().GetBytes(encoding.CSizeUint64 + hashing.CHasherSize) if _, err := LoadMessage(sett.GetSettings(), randBytes); err == nil { t.Fatal("success load incorrect message") } prng := random.NewRandom() if _, err := LoadMessage(sett.GetSettings(), prng.GetBytes(64)); err == nil { t.Fatal("success load incorrect message") } msgBytes := bytes.Join( [][]byte{ {}, // pass payload hashing.NewHasher([]byte{}).ToBytes(), }, []byte{}, ) if _, err := LoadMessage(sett.GetSettings(), msgBytes); err == nil { t.Fatal("success load incorrect payload") } if _, err := LoadMessage(sett.GetSettings(), tNewInvalidMessage1(sett, pld).ToBytes()); err == nil { t.Fatal("success load invalid message 1") } if _, err := LoadMessage(sett.GetSettings(), tNewInvalidMessage2(sett, pld).ToBytes()); err == nil { t.Fatal("success load invalid message 2") } } func tNewInvalidMessage1(pSett IConstructSettings, pPld []byte) IMessage { sett := pSett.GetSettings() bytesJoiner := pPld keyBuilder := keybuilder.NewKeyBuilder(0, []byte{}) // the network_key must have good entropy key := keyBuilder.Build(tcNetworkKey, symmetric.CCipherKeySize) hash := hashing.NewHMACHasher(key, bytesJoiner).ToBytes() hash[0] ^= 1 proof := puzzle.NewPoWPuzzle(sett.GetWorkSizeBits()).ProofBytes(hash, pSett.GetParallel()) proofBytes := encoding.Uint64ToBytes(proof) cipher := symmetric.NewCipherCFB(key) return &sMessage{ fEncd: cipher.EncryptBytes(bytes.Join( [][]byte{ proofBytes[:], hash, bytesJoiner, }, []byte{}, )), fHash: hash, fProof: proof, fBody: pPld, } } func tNewInvalidMessage2(pSett IConstructSettings, pPld []byte) IMessage { sett := pSett.GetSettings() bytesJoiner := []byte{111} keyBuilder := keybuilder.NewKeyBuilder(0, []byte{}) // the network_key must have good entropy key := keyBuilder.Build(tcNetworkKey, symmetric.CCipherKeySize) hash := hashing.NewHMACHasher(key, bytesJoiner).ToBytes() proof := puzzle.NewPoWPuzzle(sett.GetWorkSizeBits()).ProofBytes(hash, pSett.GetParallel()) proofBytes := encoding.Uint64ToBytes(proof) cipher := symmetric.NewCipherCFB(key) return &sMessage{ fEncd: cipher.EncryptBytes(bytes.Join( [][]byte{ proofBytes[:], hash, pPld, }, []byte{}, )), fHash: hash, fProof: proof, fBody: pPld, } }