contracts_quorum_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. package vm
  2. import (
  3. "crypto/ecdsa"
  4. "encoding/json"
  5. "errors"
  6. "testing"
  7. "github.com/ethereum/go-ethereum/common"
  8. "github.com/ethereum/go-ethereum/core/types"
  9. "github.com/ethereum/go-ethereum/crypto"
  10. "github.com/ethereum/go-ethereum/private"
  11. "github.com/ethereum/go-ethereum/private/mock_private"
  12. "github.com/golang/mock/gomock"
  13. "github.com/stretchr/testify/require"
  14. )
  15. var (
  16. sender common.Address
  17. senderPrivateKey *ecdsa.PrivateKey
  18. tmPrivateTxHash common.EncryptedPayloadHash
  19. pmtData []byte
  20. )
  21. func init() {
  22. sender = common.HexToAddress("0xed9d02e382b34818e88b88a309c7fe71e65f419d")
  23. senderPrivateKey, _ = crypto.HexToECDSA("e6181caaffff94a09d7e332fc8da9884d99902c7874eb74354bdcadf411929f1")
  24. privateTxHash := crypto.Keccak512([]byte("encrypted-private-tx"))
  25. for i := 0; i < 64; i++ {
  26. tmPrivateTxHash[i] = privateTxHash[i]
  27. }
  28. pmtData = append(sender.Bytes(), privateTxHash...)
  29. }
  30. func TestPrivacyMarker_Run_UnsupportedTransaction_DoesNothing(t *testing.T) {
  31. publicContractCreationTx := types.NewContractCreation(0, nil, 0, nil, []byte{})
  32. privatePrivacyMarkerTx := types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, []byte{})
  33. privatePrivacyMarkerTx.SetPrivate()
  34. require.True(t, privatePrivacyMarkerTx.IsPrivacyMarker())
  35. require.True(t, privatePrivacyMarkerTx.IsPrivate())
  36. tests := []struct {
  37. name string
  38. currentTx *types.Transaction
  39. }{
  40. {
  41. name: "is-nil",
  42. currentTx: nil,
  43. },
  44. {
  45. name: "is-not-privacy-marker-tx",
  46. currentTx: publicContractCreationTx,
  47. },
  48. {
  49. name: "is-private-privacy-marker-tx",
  50. currentTx: privatePrivacyMarkerTx,
  51. },
  52. }
  53. for _, tt := range tests {
  54. t.Run(tt.name, func(t *testing.T) {
  55. ctrl := gomock.NewController(t)
  56. pm := privacyMarker{}
  57. publicState := NewMockStateDB(ctrl)
  58. innerApplier := &stubInnerApplier{}
  59. evm := &EVM{
  60. currentTx: tt.currentTx,
  61. publicState: publicState,
  62. InnerApply: innerApplier.InnerApply,
  63. }
  64. publicState.EXPECT().SetNonce(gomock.Any(), gomock.Any()).Times(0)
  65. gotByt, gotErr := pm.Run(evm, []byte{})
  66. require.False(t, innerApplier.wasCalled())
  67. require.Nil(t, gotByt)
  68. require.Nil(t, gotErr)
  69. ctrl.Finish()
  70. })
  71. }
  72. }
  73. func TestPrivacyMarker_Run_NonZeroEVMDepth_DoesNothing(t *testing.T) {
  74. ctrl := gomock.NewController(t)
  75. defer ctrl.Finish()
  76. privacyMarkerTx := types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, []byte{})
  77. require.True(t, privacyMarkerTx.IsPrivacyMarker())
  78. pm := privacyMarker{}
  79. publicState := NewMockStateDB(ctrl)
  80. innerApplier := &stubInnerApplier{}
  81. depth := 1
  82. evm := &EVM{
  83. depth: depth,
  84. currentTx: privacyMarkerTx,
  85. publicState: publicState,
  86. InnerApply: innerApplier.InnerApply,
  87. }
  88. publicState.EXPECT().SetNonce(gomock.Any(), gomock.Any()).Times(0)
  89. gotByt, gotErr := pm.Run(evm, []byte{})
  90. require.False(t, innerApplier.wasCalled())
  91. require.Nil(t, gotByt)
  92. require.Nil(t, gotErr)
  93. }
  94. func TestPrivacyMarker_Run_InvalidTransaction_NonceUnchanged(t *testing.T) {
  95. var (
  96. publicTx *types.Transaction
  97. publicTxByt []byte
  98. unsignedPrivateTx *types.Transaction
  99. incorrectlySignedPrivateTx *types.Transaction
  100. incorrectlySignedPrivateTxByt []byte
  101. setupErr error
  102. )
  103. publicTx = types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, []byte{})
  104. require.False(t, publicTx.IsPrivate())
  105. publicTxByt, setupErr = json.Marshal(publicTx)
  106. if setupErr != nil {
  107. t.Fatalf("unable to marshal tx to json, err = %v", setupErr)
  108. }
  109. unsignedPrivateTx = types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, []byte{})
  110. unsignedPrivateTx.SetPrivate()
  111. invalidSig := common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")
  112. incorrectlySignedPrivateTx, setupErr = unsignedPrivateTx.WithSignature(
  113. types.QuorumPrivateTxSigner{},
  114. invalidSig,
  115. )
  116. if setupErr != nil {
  117. t.Fatalf("unable to sign tx, err = %v", setupErr)
  118. }
  119. require.True(t, incorrectlySignedPrivateTx.IsPrivate())
  120. incorrectlySignedPrivateTxByt, setupErr = json.Marshal(incorrectlySignedPrivateTx)
  121. if setupErr != nil {
  122. t.Fatalf("unable to marshal tx to json, err = %v", setupErr)
  123. }
  124. tests := []struct {
  125. name string
  126. privacyManagerResp []byte // decrypted data from privacy manager
  127. privacyManagerErr error
  128. }{
  129. {
  130. name: "privacy-manager-error",
  131. privacyManagerResp: nil,
  132. privacyManagerErr: errors.New("some error like node is down"),
  133. },
  134. {
  135. name: "non-participant",
  136. privacyManagerResp: nil,
  137. privacyManagerErr: nil,
  138. },
  139. {
  140. name: "internal-tx-is-not-private",
  141. privacyManagerResp: publicTxByt,
  142. privacyManagerErr: nil,
  143. },
  144. {
  145. name: "internal-private-tx-has-invalid-signature",
  146. privacyManagerResp: incorrectlySignedPrivateTxByt,
  147. privacyManagerErr: nil,
  148. },
  149. }
  150. for _, tt := range tests {
  151. t.Run(tt.name, func(t *testing.T) {
  152. ctrl := gomock.NewController(t)
  153. unsignedPrivacyMarkerTx := types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, pmtData)
  154. signer := types.HomesteadSigner{}
  155. txHash := signer.Hash(unsignedPrivacyMarkerTx)
  156. validSig, setupErr := crypto.Sign(txHash.Bytes(), senderPrivateKey)
  157. if setupErr != nil {
  158. t.Fatalf("unable to sign tx, err = %v", setupErr)
  159. }
  160. privacyMarkerTx, setupErr := unsignedPrivacyMarkerTx.WithSignature(
  161. signer,
  162. validSig,
  163. )
  164. if setupErr != nil {
  165. t.Fatalf("unable to sign tx, err = %v", setupErr)
  166. }
  167. require.True(t, privacyMarkerTx.IsPrivacyMarker())
  168. pm := privacyMarker{}
  169. privacyManager := mock_private.NewMockPrivateTransactionManager(ctrl)
  170. private.P = privacyManager
  171. publicState := NewMockStateDB(ctrl)
  172. innerApplier := nonceIncrementingInnerApplier{
  173. incrementNonceFunc: func() {
  174. // this should not be called
  175. publicState.SetNonce(sender, 1)
  176. },
  177. }
  178. evm := &EVM{
  179. currentTx: privacyMarkerTx,
  180. publicState: publicState,
  181. InnerApply: innerApplier.InnerApply,
  182. }
  183. privacyManager.EXPECT().Receive(tmPrivateTxHash).Return("", []string{}, tt.privacyManagerResp, nil, tt.privacyManagerErr)
  184. publicState.EXPECT().GetNonce(gomock.Any()).Times(0)
  185. publicState.EXPECT().SetNonce(gomock.Any(), gomock.Any()).Times(0)
  186. gotByt, gotErr := pm.Run(evm, []byte{})
  187. require.False(t, innerApplier.wasCalled())
  188. require.Nil(t, gotByt)
  189. require.Nil(t, gotErr)
  190. defer ctrl.Finish()
  191. })
  192. }
  193. }
  194. func TestPrivacyMarker_Run_SupportedTransaction_ExecutionFails_NonceUnchanged(t *testing.T) {
  195. var (
  196. unsignedPrivateTx *types.Transaction
  197. signedPrivateTx *types.Transaction
  198. signedPrivateTxByt []byte
  199. setupErr error
  200. )
  201. unsignedPrivateTx = types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, []byte{})
  202. unsignedPrivateTx.SetPrivate()
  203. signer := types.QuorumPrivateTxSigner{}
  204. txHash := signer.Hash(unsignedPrivateTx)
  205. validSig, setupErr := crypto.Sign(txHash.Bytes(), senderPrivateKey)
  206. if setupErr != nil {
  207. t.Fatalf("unable to sign tx, err = %v", setupErr)
  208. }
  209. signedPrivateTx, setupErr = unsignedPrivateTx.WithSignature(
  210. types.QuorumPrivateTxSigner{},
  211. validSig,
  212. )
  213. if setupErr != nil {
  214. t.Fatalf("unable to sign tx, err = %v", setupErr)
  215. }
  216. require.True(t, signedPrivateTx.IsPrivate())
  217. signedPrivateTxByt, setupErr = json.Marshal(signedPrivateTx)
  218. if setupErr != nil {
  219. t.Fatalf("unable to marshal tx to json, err = %v", setupErr)
  220. }
  221. tests := []struct {
  222. name string
  223. innerApplier innerApplier
  224. }{
  225. {
  226. name: "internal-private-tx-execution-fails",
  227. innerApplier: &failingInnerApplier{},
  228. },
  229. {
  230. name: "internal-private-tx-execution-does-not-increment-nonce",
  231. innerApplier: &stubInnerApplier{},
  232. },
  233. }
  234. for _, tt := range tests {
  235. t.Run(tt.name, func(t *testing.T) {
  236. ctrl := gomock.NewController(t)
  237. unsignedPrivacyMarkerTx := types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, pmtData)
  238. signer := types.HomesteadSigner{}
  239. txHash := signer.Hash(unsignedPrivacyMarkerTx)
  240. validSig, setupErr := crypto.Sign(txHash.Bytes(), senderPrivateKey)
  241. if setupErr != nil {
  242. t.Fatalf("unable to sign tx, err = %v", setupErr)
  243. }
  244. privacyMarkerTx, setupErr := unsignedPrivacyMarkerTx.WithSignature(
  245. signer,
  246. validSig,
  247. )
  248. if setupErr != nil {
  249. t.Fatalf("unable to sign tx, err = %v", setupErr)
  250. }
  251. require.True(t, privacyMarkerTx.IsPrivacyMarker())
  252. pm := privacyMarker{}
  253. privacyManager := mock_private.NewMockPrivateTransactionManager(ctrl)
  254. private.P = privacyManager
  255. publicState := NewMockStateDB(ctrl)
  256. evm := &EVM{
  257. currentTx: privacyMarkerTx,
  258. publicState: publicState,
  259. InnerApply: tt.innerApplier.InnerApply,
  260. }
  261. var (
  262. senderCurrentNonce uint64 = 10
  263. senderPreviousNonce uint64 = 9
  264. )
  265. privacyManager.EXPECT().Receive(tmPrivateTxHash).Return("", []string{}, signedPrivateTxByt, nil, nil)
  266. gomock.InOrder(
  267. publicState.EXPECT().GetNonce(sender).Return(senderCurrentNonce).Times(1), // getting startingNonce
  268. publicState.EXPECT().SetNonce(sender, senderPreviousNonce).Times(1), // decrementing nonce to prepare for pvt tx execution
  269. publicState.EXPECT().SetNonce(sender, senderCurrentNonce).Times(1), // resetting nonce to startingNonce
  270. )
  271. gotByt, gotErr := pm.Run(evm, []byte{})
  272. require.True(t, tt.innerApplier.wasCalled())
  273. require.Nil(t, gotByt)
  274. require.Nil(t, gotErr)
  275. executedTx := tt.innerApplier.innerTx()
  276. // we only want to compare the values that matter in the embedded txdata - this is unexported so we resort to
  277. // using the string representation of the txs for comparison
  278. require.EqualValues(t, signedPrivateTx.String(), executedTx.String())
  279. defer ctrl.Finish()
  280. })
  281. }
  282. }
  283. func TestPrivacyMarker_Run_SupportedTransaction_ExecutionSucceeds_NonceUnchanged(t *testing.T) {
  284. ctrl := gomock.NewController(t)
  285. defer ctrl.Finish()
  286. var (
  287. unsignedPrivateTx *types.Transaction
  288. signedPrivateTx *types.Transaction
  289. signedPrivateTxByt []byte
  290. setupErr error
  291. )
  292. unsignedPrivateTx = types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, []byte{})
  293. unsignedPrivateTx.SetPrivate()
  294. signer := types.QuorumPrivateTxSigner{}
  295. txHash := signer.Hash(unsignedPrivateTx)
  296. validSig, setupErr := crypto.Sign(txHash.Bytes(), senderPrivateKey)
  297. if setupErr != nil {
  298. t.Fatalf("unable to sign tx, err = %v", setupErr)
  299. }
  300. signedPrivateTx, setupErr = unsignedPrivateTx.WithSignature(
  301. types.QuorumPrivateTxSigner{},
  302. validSig,
  303. )
  304. if setupErr != nil {
  305. t.Fatalf("unable to sign tx, err = %v", setupErr)
  306. }
  307. require.True(t, signedPrivateTx.IsPrivate())
  308. signedPrivateTxByt, setupErr = json.Marshal(signedPrivateTx)
  309. if setupErr != nil {
  310. t.Fatalf("unable to marshal tx to json, err = %v", setupErr)
  311. }
  312. unsignedPrivacyMarkerTx := types.NewTransaction(0, common.QuorumPrivacyPrecompileContractAddress(), nil, 0, nil, pmtData)
  313. ptmSigner := types.HomesteadSigner{}
  314. ptmHash := ptmSigner.Hash(unsignedPrivacyMarkerTx)
  315. validSig, setupErr = crypto.Sign(ptmHash.Bytes(), senderPrivateKey)
  316. if setupErr != nil {
  317. t.Fatalf("unable to sign tx, err = %v", setupErr)
  318. }
  319. privacyMarkerTx, setupErr := unsignedPrivacyMarkerTx.WithSignature(
  320. ptmSigner,
  321. validSig,
  322. )
  323. if setupErr != nil {
  324. t.Fatalf("unable to sign tx, err = %v", setupErr)
  325. }
  326. require.True(t, privacyMarkerTx.IsPrivacyMarker())
  327. pm := privacyMarker{}
  328. privacyManager := mock_private.NewMockPrivateTransactionManager(ctrl)
  329. private.P = privacyManager
  330. publicState := NewMockStateDB(ctrl)
  331. var (
  332. senderCurrentNonce uint64 = 10
  333. senderPreviousNonce uint64 = 9
  334. )
  335. innerApplier := nonceIncrementingInnerApplier{
  336. incrementNonceFunc: func() {
  337. publicState.SetNonce(sender, senderPreviousNonce+1)
  338. },
  339. }
  340. evm := &EVM{
  341. currentTx: privacyMarkerTx,
  342. publicState: publicState,
  343. InnerApply: innerApplier.InnerApply,
  344. }
  345. privacyManager.EXPECT().Receive(tmPrivateTxHash).Return("", []string{}, signedPrivateTxByt, nil, nil)
  346. gomock.InOrder(
  347. publicState.EXPECT().GetNonce(sender).Return(senderCurrentNonce).Times(1), // getting startingNonce
  348. publicState.EXPECT().SetNonce(sender, senderPreviousNonce).Times(1), // decrementing nonce to prepare for pvt tx execution
  349. publicState.EXPECT().SetNonce(sender, senderCurrentNonce).Times(1), // the call in nonceIncrementingInnerApplier
  350. publicState.EXPECT().SetNonce(sender, senderCurrentNonce).Times(1), // resetting nonce to startingNonce
  351. )
  352. gotByt, gotErr := pm.Run(evm, []byte{})
  353. require.True(t, innerApplier.wasCalled())
  354. require.Nil(t, gotByt)
  355. require.Nil(t, gotErr)
  356. executedTx := innerApplier.innerTx()
  357. // we only want to compare the values the matter in the embedded txdata - this is unexported so we resort to
  358. // using the string representation of the txs for comparison
  359. require.EqualValues(t, signedPrivateTx.String(), executedTx.String())
  360. }
  361. type innerApplier interface {
  362. InnerApply(innerTx *types.Transaction) error
  363. wasCalled() bool
  364. innerTx() *types.Transaction
  365. }
  366. type stubInnerApplier struct {
  367. called bool
  368. tx *types.Transaction
  369. }
  370. func (m *stubInnerApplier) InnerApply(innerTx *types.Transaction) error {
  371. m.called = true
  372. m.tx = innerTx
  373. return nil
  374. }
  375. func (m *stubInnerApplier) wasCalled() bool {
  376. return m.called
  377. }
  378. func (m *stubInnerApplier) innerTx() *types.Transaction {
  379. return m.tx
  380. }
  381. type failingInnerApplier struct {
  382. called bool
  383. tx *types.Transaction
  384. }
  385. func (m *failingInnerApplier) InnerApply(innerTx *types.Transaction) error {
  386. m.called = true
  387. m.tx = innerTx
  388. return errors.New("some error")
  389. }
  390. func (m *failingInnerApplier) wasCalled() bool {
  391. return m.called
  392. }
  393. func (m *failingInnerApplier) innerTx() *types.Transaction {
  394. return m.tx
  395. }
  396. type nonceIncrementingInnerApplier struct {
  397. called bool
  398. tx *types.Transaction
  399. incrementNonceFunc func()
  400. }
  401. func (m *nonceIncrementingInnerApplier) InnerApply(innerTx *types.Transaction) error {
  402. m.called = true
  403. m.tx = innerTx
  404. m.incrementNonceFunc()
  405. return nil
  406. }
  407. func (m *nonceIncrementingInnerApplier) wasCalled() bool {
  408. return m.called
  409. }
  410. func (m *nonceIncrementingInnerApplier) innerTx() *types.Transaction {
  411. return m.tx
  412. }