You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.3 KiB

  1. package secretconnection
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "log"
  7. "github.com/tendermint/tendermint/crypto/ed25519"
  8. "github.com/tendermint/tendermint/internal/libs/async"
  9. sc "github.com/tendermint/tendermint/internal/p2p/conn"
  10. )
  11. func Fuzz(data []byte) int {
  12. if len(data) == 0 {
  13. return -1
  14. }
  15. fooConn, barConn := makeSecretConnPair()
  16. // Run Write in a separate goroutine because if data is greater than 1024
  17. // bytes, each Write must be followed by Read (see io.Pipe documentation).
  18. go func() {
  19. // Copy data because Write modifies the slice.
  20. dataToWrite := make([]byte, len(data))
  21. copy(dataToWrite, data)
  22. n, err := fooConn.Write(dataToWrite)
  23. if err != nil {
  24. panic(err)
  25. }
  26. if n < len(data) {
  27. panic(fmt.Sprintf("wanted to write %d bytes, but %d was written", len(data), n))
  28. }
  29. }()
  30. dataRead := make([]byte, len(data))
  31. totalRead := 0
  32. for totalRead < len(data) {
  33. buf := make([]byte, len(data)-totalRead)
  34. m, err := barConn.Read(buf)
  35. if err != nil {
  36. panic(err)
  37. }
  38. copy(dataRead[totalRead:], buf[:m])
  39. totalRead += m
  40. log.Printf("total read: %d", totalRead)
  41. }
  42. if !bytes.Equal(data, dataRead) {
  43. panic("bytes written != read")
  44. }
  45. return 1
  46. }
  47. type kvstoreConn struct {
  48. *io.PipeReader
  49. *io.PipeWriter
  50. }
  51. func (drw kvstoreConn) Close() (err error) {
  52. err2 := drw.PipeWriter.CloseWithError(io.EOF)
  53. err1 := drw.PipeReader.Close()
  54. if err2 != nil {
  55. return err
  56. }
  57. return err1
  58. }
  59. // Each returned ReadWriteCloser is akin to a net.Connection
  60. func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) {
  61. barReader, fooWriter := io.Pipe()
  62. fooReader, barWriter := io.Pipe()
  63. return kvstoreConn{fooReader, fooWriter}, kvstoreConn{barReader, barWriter}
  64. }
  65. func makeSecretConnPair() (fooSecConn, barSecConn *sc.SecretConnection) {
  66. var (
  67. fooConn, barConn = makeKVStoreConnPair()
  68. fooPrvKey = ed25519.GenPrivKey()
  69. fooPubKey = fooPrvKey.PubKey()
  70. barPrvKey = ed25519.GenPrivKey()
  71. barPubKey = barPrvKey.PubKey()
  72. )
  73. // Make connections from both sides in parallel.
  74. var trs, ok = async.Parallel(
  75. func(_ int) (val interface{}, abort bool, err error) {
  76. fooSecConn, err = sc.MakeSecretConnection(fooConn, fooPrvKey)
  77. if err != nil {
  78. log.Printf("failed to establish SecretConnection for foo: %v", err)
  79. return nil, true, err
  80. }
  81. remotePubBytes := fooSecConn.RemotePubKey()
  82. if !remotePubBytes.Equals(barPubKey) {
  83. err = fmt.Errorf("unexpected fooSecConn.RemotePubKey. Expected %v, got %v",
  84. barPubKey, fooSecConn.RemotePubKey())
  85. log.Print(err)
  86. return nil, true, err
  87. }
  88. return nil, false, nil
  89. },
  90. func(_ int) (val interface{}, abort bool, err error) {
  91. barSecConn, err = sc.MakeSecretConnection(barConn, barPrvKey)
  92. if barSecConn == nil {
  93. log.Printf("failed to establish SecretConnection for bar: %v", err)
  94. return nil, true, err
  95. }
  96. remotePubBytes := barSecConn.RemotePubKey()
  97. if !remotePubBytes.Equals(fooPubKey) {
  98. err = fmt.Errorf("unexpected barSecConn.RemotePubKey. Expected %v, got %v",
  99. fooPubKey, barSecConn.RemotePubKey())
  100. log.Print(err)
  101. return nil, true, err
  102. }
  103. return nil, false, nil
  104. },
  105. )
  106. if trs.FirstError() != nil {
  107. log.Fatalf("unexpected error: %v", trs.FirstError())
  108. }
  109. if !ok {
  110. log.Fatal("Unexpected task abortion")
  111. }
  112. return fooSecConn, barSecConn
  113. }