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.

443 lines
9.7 KiB

  1. package privval
  2. import (
  3. "fmt"
  4. "net"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "github.com/tendermint/tendermint/crypto/ed25519"
  10. cmn "github.com/tendermint/tendermint/libs/common"
  11. "github.com/tendermint/tendermint/libs/log"
  12. p2pconn "github.com/tendermint/tendermint/p2p/conn"
  13. "github.com/tendermint/tendermint/types"
  14. )
  15. func TestSocketPVAddress(t *testing.T) {
  16. var (
  17. chainID = cmn.RandStr(12)
  18. sc, rs = testSetupSocketPair(t, chainID, types.NewMockPV())
  19. )
  20. defer sc.Stop()
  21. defer rs.Stop()
  22. serverAddr := rs.privVal.GetAddress()
  23. clientAddr, err := sc.getAddress()
  24. require.NoError(t, err)
  25. assert.Equal(t, serverAddr, clientAddr)
  26. // TODO(xla): Remove when PrivValidator2 replaced PrivValidator.
  27. assert.Equal(t, serverAddr, sc.GetAddress())
  28. }
  29. func TestSocketPVPubKey(t *testing.T) {
  30. var (
  31. chainID = cmn.RandStr(12)
  32. sc, rs = testSetupSocketPair(t, chainID, types.NewMockPV())
  33. )
  34. defer sc.Stop()
  35. defer rs.Stop()
  36. clientKey, err := sc.getPubKey()
  37. require.NoError(t, err)
  38. privKey := rs.privVal.GetPubKey()
  39. assert.Equal(t, privKey, clientKey)
  40. // TODO(xla): Remove when PrivValidator2 replaced PrivValidator.
  41. assert.Equal(t, privKey, sc.GetPubKey())
  42. }
  43. func TestSocketPVProposal(t *testing.T) {
  44. var (
  45. chainID = cmn.RandStr(12)
  46. sc, rs = testSetupSocketPair(t, chainID, types.NewMockPV())
  47. ts = time.Now()
  48. privProposal = &types.Proposal{Timestamp: ts}
  49. clientProposal = &types.Proposal{Timestamp: ts}
  50. )
  51. defer sc.Stop()
  52. defer rs.Stop()
  53. require.NoError(t, rs.privVal.SignProposal(chainID, privProposal))
  54. require.NoError(t, sc.SignProposal(chainID, clientProposal))
  55. assert.Equal(t, privProposal.Signature, clientProposal.Signature)
  56. }
  57. func TestSocketPVVote(t *testing.T) {
  58. var (
  59. chainID = cmn.RandStr(12)
  60. sc, rs = testSetupSocketPair(t, chainID, types.NewMockPV())
  61. ts = time.Now()
  62. vType = types.PrecommitType
  63. want = &types.Vote{Timestamp: ts, Type: vType}
  64. have = &types.Vote{Timestamp: ts, Type: vType}
  65. )
  66. defer sc.Stop()
  67. defer rs.Stop()
  68. require.NoError(t, rs.privVal.SignVote(chainID, want))
  69. require.NoError(t, sc.SignVote(chainID, have))
  70. assert.Equal(t, want.Signature, have.Signature)
  71. }
  72. func TestSocketPVHeartbeat(t *testing.T) {
  73. var (
  74. chainID = cmn.RandStr(12)
  75. sc, rs = testSetupSocketPair(t, chainID, types.NewMockPV())
  76. want = &types.Heartbeat{}
  77. have = &types.Heartbeat{}
  78. )
  79. defer sc.Stop()
  80. defer rs.Stop()
  81. require.NoError(t, rs.privVal.SignHeartbeat(chainID, want))
  82. require.NoError(t, sc.SignHeartbeat(chainID, have))
  83. assert.Equal(t, want.Signature, have.Signature)
  84. }
  85. func TestSocketPVAcceptDeadline(t *testing.T) {
  86. var (
  87. sc = NewSocketPV(
  88. log.TestingLogger(),
  89. "127.0.0.1:0",
  90. ed25519.GenPrivKey(),
  91. )
  92. )
  93. defer sc.Stop()
  94. SocketPVAcceptDeadline(time.Millisecond)(sc)
  95. assert.Equal(t, sc.Start().(cmn.Error).Data(), ErrConnWaitTimeout)
  96. }
  97. func TestSocketPVDeadline(t *testing.T) {
  98. var (
  99. addr = testFreeAddr(t)
  100. listenc = make(chan struct{})
  101. sc = NewSocketPV(
  102. log.TestingLogger(),
  103. addr,
  104. ed25519.GenPrivKey(),
  105. )
  106. )
  107. SocketPVConnDeadline(100 * time.Millisecond)(sc)
  108. SocketPVConnWait(500 * time.Millisecond)(sc)
  109. go func(sc *SocketPV) {
  110. defer close(listenc)
  111. require.NoError(t, sc.Start())
  112. assert.True(t, sc.IsRunning())
  113. }(sc)
  114. for {
  115. conn, err := cmn.Connect(addr)
  116. if err != nil {
  117. continue
  118. }
  119. _, err = p2pconn.MakeSecretConnection(
  120. conn,
  121. ed25519.GenPrivKey(),
  122. )
  123. if err == nil {
  124. break
  125. }
  126. }
  127. <-listenc
  128. // Sleep to guarantee deadline has been hit.
  129. time.Sleep(20 * time.Microsecond)
  130. _, err := sc.getPubKey()
  131. assert.Equal(t, err.(cmn.Error).Data(), ErrConnTimeout)
  132. }
  133. func TestSocketPVWait(t *testing.T) {
  134. sc := NewSocketPV(
  135. log.TestingLogger(),
  136. "127.0.0.1:0",
  137. ed25519.GenPrivKey(),
  138. )
  139. defer sc.Stop()
  140. SocketPVConnWait(time.Millisecond)(sc)
  141. assert.Equal(t, sc.Start().(cmn.Error).Data(), ErrConnWaitTimeout)
  142. }
  143. func TestRemoteSignerRetry(t *testing.T) {
  144. var (
  145. attemptc = make(chan int)
  146. retries = 2
  147. )
  148. ln, err := net.Listen("tcp", "127.0.0.1:0")
  149. require.NoError(t, err)
  150. go func(ln net.Listener, attemptc chan<- int) {
  151. attempts := 0
  152. for {
  153. conn, err := ln.Accept()
  154. require.NoError(t, err)
  155. err = conn.Close()
  156. require.NoError(t, err)
  157. attempts++
  158. if attempts == retries {
  159. attemptc <- attempts
  160. break
  161. }
  162. }
  163. }(ln, attemptc)
  164. rs := NewRemoteSigner(
  165. log.TestingLogger(),
  166. cmn.RandStr(12),
  167. ln.Addr().String(),
  168. types.NewMockPV(),
  169. ed25519.GenPrivKey(),
  170. )
  171. defer rs.Stop()
  172. RemoteSignerConnDeadline(time.Millisecond)(rs)
  173. RemoteSignerConnRetries(retries)(rs)
  174. assert.Equal(t, rs.Start().(cmn.Error).Data(), ErrDialRetryMax)
  175. select {
  176. case attempts := <-attemptc:
  177. assert.Equal(t, retries, attempts)
  178. case <-time.After(100 * time.Millisecond):
  179. t.Error("expected remote to observe connection attempts")
  180. }
  181. }
  182. func TestRemoteSignVoteErrors(t *testing.T) {
  183. var (
  184. chainID = cmn.RandStr(12)
  185. sc, rs = testSetupSocketPair(t, chainID, types.NewErroringMockPV())
  186. ts = time.Now()
  187. vType = types.PrecommitType
  188. vote = &types.Vote{Timestamp: ts, Type: vType}
  189. )
  190. defer sc.Stop()
  191. defer rs.Stop()
  192. err := writeMsg(sc.conn, &SignVoteRequest{Vote: vote})
  193. require.NoError(t, err)
  194. res, err := readMsg(sc.conn)
  195. require.NoError(t, err)
  196. resp := *res.(*SignedVoteResponse)
  197. require.NotNil(t, resp.Error)
  198. require.Equal(t, resp.Error.Description, types.ErroringMockPVErr.Error())
  199. err = rs.privVal.SignVote(chainID, vote)
  200. require.Error(t, err)
  201. err = sc.SignVote(chainID, vote)
  202. require.Error(t, err)
  203. }
  204. func TestRemoteSignProposalErrors(t *testing.T) {
  205. var (
  206. chainID = cmn.RandStr(12)
  207. sc, rs = testSetupSocketPair(t, chainID, types.NewErroringMockPV())
  208. ts = time.Now()
  209. proposal = &types.Proposal{Timestamp: ts}
  210. )
  211. defer sc.Stop()
  212. defer rs.Stop()
  213. err := writeMsg(sc.conn, &SignProposalRequest{Proposal: proposal})
  214. require.NoError(t, err)
  215. res, err := readMsg(sc.conn)
  216. require.NoError(t, err)
  217. resp := *res.(*SignedProposalResponse)
  218. require.NotNil(t, resp.Error)
  219. require.Equal(t, resp.Error.Description, types.ErroringMockPVErr.Error())
  220. err = rs.privVal.SignProposal(chainID, proposal)
  221. require.Error(t, err)
  222. err = sc.SignProposal(chainID, proposal)
  223. require.Error(t, err)
  224. }
  225. func TestRemoteSignHeartbeatErrors(t *testing.T) {
  226. var (
  227. chainID = cmn.RandStr(12)
  228. sc, rs = testSetupSocketPair(t, chainID, types.NewErroringMockPV())
  229. hb = &types.Heartbeat{}
  230. )
  231. defer sc.Stop()
  232. defer rs.Stop()
  233. err := writeMsg(sc.conn, &SignHeartbeatRequest{Heartbeat: hb})
  234. require.NoError(t, err)
  235. res, err := readMsg(sc.conn)
  236. require.NoError(t, err)
  237. resp := *res.(*SignedHeartbeatResponse)
  238. require.NotNil(t, resp.Error)
  239. require.Equal(t, resp.Error.Description, types.ErroringMockPVErr.Error())
  240. err = rs.privVal.SignHeartbeat(chainID, hb)
  241. require.Error(t, err)
  242. err = sc.SignHeartbeat(chainID, hb)
  243. require.Error(t, err)
  244. }
  245. func TestErrUnexpectedResponse(t *testing.T) {
  246. var (
  247. addr = testFreeAddr(t)
  248. logger = log.TestingLogger()
  249. chainID = cmn.RandStr(12)
  250. readyc = make(chan struct{})
  251. errc = make(chan error, 1)
  252. rs = NewRemoteSigner(
  253. logger,
  254. chainID,
  255. addr,
  256. types.NewMockPV(),
  257. ed25519.GenPrivKey(),
  258. )
  259. sc = NewSocketPV(
  260. logger,
  261. addr,
  262. ed25519.GenPrivKey(),
  263. )
  264. )
  265. testStartSocketPV(t, readyc, sc)
  266. defer sc.Stop()
  267. RemoteSignerConnDeadline(time.Millisecond)(rs)
  268. RemoteSignerConnRetries(1e6)(rs)
  269. // we do not want to Start() the remote signer here and instead use the connection to
  270. // reply with intentionally wrong replies below:
  271. rsConn, err := rs.connect()
  272. defer rsConn.Close()
  273. require.NoError(t, err)
  274. require.NotNil(t, rsConn)
  275. <-readyc
  276. // Heartbeat:
  277. go func(errc chan error) {
  278. errc <- sc.SignHeartbeat(chainID, &types.Heartbeat{})
  279. }(errc)
  280. // read request and write wrong response:
  281. go testReadWriteResponse(t, &SignedVoteResponse{}, rsConn)
  282. err = <-errc
  283. require.Error(t, err)
  284. require.Equal(t, err, ErrUnexpectedResponse)
  285. // Proposal:
  286. go func(errc chan error) {
  287. errc <- sc.SignProposal(chainID, &types.Proposal{})
  288. }(errc)
  289. // read request and write wrong response:
  290. go testReadWriteResponse(t, &SignedHeartbeatResponse{}, rsConn)
  291. err = <-errc
  292. require.Error(t, err)
  293. require.Equal(t, err, ErrUnexpectedResponse)
  294. // Vote:
  295. go func(errc chan error) {
  296. errc <- sc.SignVote(chainID, &types.Vote{})
  297. }(errc)
  298. // read request and write wrong response:
  299. go testReadWriteResponse(t, &SignedHeartbeatResponse{}, rsConn)
  300. err = <-errc
  301. require.Error(t, err)
  302. require.Equal(t, err, ErrUnexpectedResponse)
  303. }
  304. func testSetupSocketPair(
  305. t *testing.T,
  306. chainID string,
  307. privValidator types.PrivValidator,
  308. ) (*SocketPV, *RemoteSigner) {
  309. var (
  310. addr = testFreeAddr(t)
  311. logger = log.TestingLogger()
  312. privVal = privValidator
  313. readyc = make(chan struct{})
  314. rs = NewRemoteSigner(
  315. logger,
  316. chainID,
  317. addr,
  318. privVal,
  319. ed25519.GenPrivKey(),
  320. )
  321. sc = NewSocketPV(
  322. logger,
  323. addr,
  324. ed25519.GenPrivKey(),
  325. )
  326. )
  327. testStartSocketPV(t, readyc, sc)
  328. RemoteSignerConnDeadline(time.Millisecond)(rs)
  329. RemoteSignerConnRetries(1e6)(rs)
  330. require.NoError(t, rs.Start())
  331. assert.True(t, rs.IsRunning())
  332. <-readyc
  333. return sc, rs
  334. }
  335. func testReadWriteResponse(t *testing.T, resp SocketPVMsg, rsConn net.Conn) {
  336. _, err := readMsg(rsConn)
  337. require.NoError(t, err)
  338. err = writeMsg(rsConn, resp)
  339. require.NoError(t, err)
  340. }
  341. func testStartSocketPV(t *testing.T, readyc chan struct{}, sc *SocketPV) {
  342. go func(sc *SocketPV) {
  343. require.NoError(t, sc.Start())
  344. assert.True(t, sc.IsRunning())
  345. readyc <- struct{}{}
  346. }(sc)
  347. }
  348. // testFreeAddr claims a free port so we don't block on listener being ready.
  349. func testFreeAddr(t *testing.T) string {
  350. ln, err := net.Listen("tcp", "127.0.0.1:0")
  351. require.NoError(t, err)
  352. defer ln.Close()
  353. return fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port)
  354. }