multiple_psm_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. package core
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "math/big"
  6. "testing"
  7. "github.com/ethereum/go-ethereum/common"
  8. "github.com/ethereum/go-ethereum/consensus/ethash"
  9. "github.com/ethereum/go-ethereum/core/mps"
  10. "github.com/ethereum/go-ethereum/core/privatecache"
  11. "github.com/ethereum/go-ethereum/core/rawdb"
  12. "github.com/ethereum/go-ethereum/core/state"
  13. "github.com/ethereum/go-ethereum/core/types"
  14. "github.com/ethereum/go-ethereum/core/vm"
  15. "github.com/ethereum/go-ethereum/crypto"
  16. "github.com/ethereum/go-ethereum/params"
  17. "github.com/ethereum/go-ethereum/private"
  18. "github.com/ethereum/go-ethereum/private/engine"
  19. "github.com/ethereum/go-ethereum/rpc"
  20. "github.com/golang/mock/gomock"
  21. "github.com/stretchr/testify/assert"
  22. )
  23. const (
  24. // testCode is the testing contract binary code which will initialises some
  25. // variables in constructor
  26. testCode = "0x60806040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060005534801561003457600080fd5b5060fc806100436000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80630c4dae8814603757806398a213cf146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506084565b005b60005481565b806000819055507fe9e44f9f7da8c559de847a3232b57364adc0354f15a2cd8dc636d54396f9587a6000546040518082815260200191505060405180910390a15056fea265627a7a723058208ae31d9424f2d0bc2a3da1a5dd659db2d71ec322a17db8f87e19e209e3a1ff4a64736f6c634300050a0032"
  27. // testGas is the gas required for contract deployment.
  28. testGas = 144109
  29. )
  30. var (
  31. testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  32. testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
  33. )
  34. func buildTestChain(n int, config *params.ChainConfig) ([]*types.Block, map[common.Hash]*types.Block, *BlockChain) {
  35. testdb := rawdb.NewMemoryDatabase()
  36. genesis := GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000))
  37. blocks, _ := GenerateChain(config, genesis, ethash.NewFaker(), testdb, n, func(i int, block *BlockGen) {
  38. block.SetCoinbase(common.Address{0})
  39. signer := types.QuorumPrivateTxSigner{}
  40. tx, err := types.SignTx(types.NewContractCreation(block.TxNonce(testAddress), big.NewInt(0), testGas, nil, common.FromHex(testCode)), signer, testKey)
  41. if err != nil {
  42. panic(err)
  43. }
  44. block.AddTx(tx)
  45. })
  46. hashes := make([]common.Hash, n+1)
  47. hashes[len(hashes)-1] = genesis.Hash()
  48. blockm := make(map[common.Hash]*types.Block, n+1)
  49. blockm[genesis.Hash()] = genesis
  50. for i, b := range blocks {
  51. hashes[len(hashes)-i-2] = b.Hash()
  52. blockm[b.Hash()] = b
  53. }
  54. blockchain, _ := NewBlockChain(testdb, nil, config, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
  55. return blocks, blockm, blockchain
  56. }
  57. func TestMultiplePSMRStateCreated(t *testing.T) {
  58. mockCtrl := gomock.NewController(t)
  59. defer mockCtrl.Finish()
  60. mockptm := private.NewMockPrivateTransactionManager(mockCtrl)
  61. saved := private.P
  62. defer func() {
  63. private.P = saved
  64. }()
  65. private.P = mockptm
  66. mockpsm := mps.NewMockPrivateStateManager(mockCtrl)
  67. mockptm.EXPECT().Receive(gomock.Not(common.EncryptedPayloadHash{})).Return("", []string{"psi1", "psi2"}, common.FromHex(testCode), nil, nil).AnyTimes()
  68. mockptm.EXPECT().Receive(common.EncryptedPayloadHash{}).Return("", []string{}, common.EncryptedPayloadHash{}.Bytes(), nil, nil).AnyTimes()
  69. mockptm.EXPECT().HasFeature(engine.MultiplePrivateStates).Return(true)
  70. mockptm.EXPECT().Groups().Return(PrivacyGroups, nil).AnyTimes()
  71. mockpsm.EXPECT().ResolveForManagedParty("psi1").Return(&PSI1PSM, nil).AnyTimes()
  72. mockpsm.EXPECT().ResolveForManagedParty("psi2").Return(&PSI2PSM, nil).AnyTimes()
  73. mockpsm.EXPECT().PSIs().Return([]types.PrivateStateIdentifier{PSI1PSM.ID, PSI2PSM.ID, types.DefaultPrivateStateIdentifier, types.ToPrivateStateIdentifier("other")}).AnyTimes()
  74. blocks, blockmap, blockchain := buildTestChain(2, params.QuorumMPSTestChainConfig)
  75. cache := state.NewDatabase(blockchain.db)
  76. privateCacheProvider := privatecache.NewPrivateCacheProvider(blockchain.db, nil, cache, false)
  77. blockchain.privateStateManager = mockpsm
  78. for _, block := range blocks {
  79. parent := blockmap[block.ParentHash()]
  80. statedb, _ := state.New(parent.Root(), blockchain.StateCache(), nil)
  81. mockpsm.EXPECT().StateRepository(gomock.Any()).Return(mps.NewMultiplePrivateStateRepository(blockchain.db, cache, common.Hash{}, privateCacheProvider)).AnyTimes()
  82. privateStateRepo, err := blockchain.PrivateStateManager().StateRepository(parent.Root())
  83. assert.NoError(t, err)
  84. publicReceipts, privateReceipts, _, _, _ := blockchain.Processor().Process(block, statedb, privateStateRepo, vm.Config{})
  85. //managed states tests
  86. for _, privateReceipt := range privateReceipts {
  87. expectedContractAddress := privateReceipt.ContractAddress
  88. emptyState, _ := privateStateRepo.DefaultState()
  89. assert.True(t, emptyState.Exist(expectedContractAddress))
  90. assert.Equal(t, emptyState.GetCodeSize(expectedContractAddress), 0)
  91. ps1, _ := privateStateRepo.StatePSI(types.PrivateStateIdentifier("psi1"))
  92. assert.True(t, ps1.Exist(expectedContractAddress))
  93. assert.NotEqual(t, ps1.GetCodeSize(expectedContractAddress), 0)
  94. ps2, _ := privateStateRepo.StatePSI(types.PrivateStateIdentifier("psi2"))
  95. assert.True(t, ps2.Exist(expectedContractAddress))
  96. assert.NotEqual(t, ps2.GetCodeSize(expectedContractAddress), 0)
  97. }
  98. //CommitAndWrite to db
  99. privateStateRepo.CommitAndWrite(false, block)
  100. //managed states test
  101. for _, privateReceipt := range privateReceipts {
  102. expectedContractAddress := privateReceipt.ContractAddress
  103. latestBlockRoot := block.Root()
  104. _, privDb, _ := blockchain.StateAtPSI(latestBlockRoot, types.ToPrivateStateIdentifier("empty"))
  105. assert.True(t, privDb.Exist(expectedContractAddress))
  106. assert.Equal(t, privDb.GetCodeSize(expectedContractAddress), 0)
  107. //contract exists on both psi states
  108. _, privDb, _ = blockchain.StateAtPSI(latestBlockRoot, types.PrivateStateIdentifier("psi1"))
  109. assert.True(t, privDb.Exist(expectedContractAddress))
  110. assert.NotEqual(t, privDb.GetCodeSize(expectedContractAddress), 0)
  111. _, privDb, _ = blockchain.StateAtPSI(latestBlockRoot, types.PrivateStateIdentifier("psi2"))
  112. assert.True(t, privDb.Exist(expectedContractAddress))
  113. assert.NotEqual(t, privDb.GetCodeSize(expectedContractAddress), 0)
  114. //contract should exist on default private state but no contract code
  115. _, privDb, _ = blockchain.StateAtPSI(latestBlockRoot, types.DefaultPrivateStateIdentifier)
  116. assert.True(t, privDb.Exist(expectedContractAddress))
  117. assert.Equal(t, privDb.GetCodeSize(expectedContractAddress), 0)
  118. //contract should exist on random state but no contract code
  119. _, privDb, _ = blockchain.StateAtPSI(latestBlockRoot, types.ToPrivateStateIdentifier("other"))
  120. assert.True(t, privDb.Exist(expectedContractAddress))
  121. assert.Equal(t, privDb.GetCodeSize(expectedContractAddress), 0)
  122. }
  123. //mergeReceipts test
  124. for _, pubReceipt := range publicReceipts {
  125. assert.Equal(t, 0, len(pubReceipt.PSReceipts))
  126. }
  127. for _, privReceipt := range privateReceipts {
  128. assert.Equal(t, 2, len(privReceipt.PSReceipts))
  129. assert.NotEqual(t, nil, privReceipt.PSReceipts["psi1"])
  130. assert.NotEqual(t, nil, privReceipt.PSReceipts["psi2"])
  131. }
  132. allReceipts := privateStateRepo.MergeReceipts(publicReceipts, privateReceipts)
  133. for _, receipt := range allReceipts {
  134. assert.Equal(t, 3, len(receipt.PSReceipts))
  135. assert.NotEqual(t, nil, receipt.PSReceipts["empty"])
  136. assert.NotEqual(t, nil, receipt.PSReceipts["psi1"])
  137. assert.NotEqual(t, nil, receipt.PSReceipts["psi2"])
  138. }
  139. }
  140. }
  141. func TestMPSReset(t *testing.T) {
  142. mockCtrl := gomock.NewController(t)
  143. defer mockCtrl.Finish()
  144. mockptm := private.NewMockPrivateTransactionManager(mockCtrl)
  145. saved := private.P
  146. defer func() {
  147. private.P = saved
  148. }()
  149. private.P = mockptm
  150. mockpsm := mps.NewMockPrivateStateManager(mockCtrl)
  151. mockptm.EXPECT().Receive(gomock.Not(common.EncryptedPayloadHash{})).Return("", []string{"psi1", "psi2"}, common.FromHex(testCode), nil, nil).AnyTimes()
  152. mockptm.EXPECT().Receive(common.EncryptedPayloadHash{}).Return("", []string{}, common.EncryptedPayloadHash{}.Bytes(), nil, nil).AnyTimes()
  153. mockptm.EXPECT().HasFeature(engine.MultiplePrivateStates).Return(true)
  154. mockptm.EXPECT().Groups().Return(PrivacyGroups, nil).AnyTimes()
  155. mockpsm.EXPECT().ResolveForManagedParty("psi1").Return(&PSI1PSM, nil).AnyTimes()
  156. mockpsm.EXPECT().ResolveForManagedParty("psi2").Return(&PSI2PSM, nil).AnyTimes()
  157. mockpsm.EXPECT().PSIs().Return([]types.PrivateStateIdentifier{PSI1PSM.ID, PSI2PSM.ID}).AnyTimes()
  158. blocks, blockmap, blockchain := buildTestChain(2, params.QuorumMPSTestChainConfig)
  159. blockchain.privateStateManager = mockpsm
  160. cache := state.NewDatabase(blockchain.db)
  161. privateCacheProvider := privatecache.NewPrivateCacheProvider(blockchain.db, nil, cache, false)
  162. for _, block := range blocks {
  163. parent := blockmap[block.ParentHash()]
  164. statedb, _ := state.New(parent.Root(), blockchain.StateCache(), nil)
  165. mockpsm.EXPECT().StateRepository(gomock.Any()).Return(mps.NewMultiplePrivateStateRepository(blockchain.db, cache, common.Hash{}, privateCacheProvider)).AnyTimes()
  166. privateStateRepo, err := blockchain.PrivateStateManager().StateRepository(parent.Root())
  167. assert.NoError(t, err)
  168. _, privateReceipts, _, _, _ := blockchain.Processor().Process(block, statedb, privateStateRepo, vm.Config{})
  169. for _, privateReceipt := range privateReceipts {
  170. expectedContractAddress := privateReceipt.ContractAddress
  171. emptyState, _ := privateStateRepo.DefaultState()
  172. assert.True(t, emptyState.Exist(expectedContractAddress))
  173. assert.Equal(t, emptyState.GetCodeSize(expectedContractAddress), 0)
  174. ps1, _ := privateStateRepo.StatePSI(types.PrivateStateIdentifier("psi1"))
  175. assert.True(t, ps1.Exist(expectedContractAddress))
  176. assert.NotEqual(t, ps1.GetCodeSize(expectedContractAddress), 0)
  177. ps2, _ := privateStateRepo.StatePSI(types.PrivateStateIdentifier("psi2"))
  178. assert.True(t, ps2.Exist(expectedContractAddress))
  179. assert.NotEqual(t, ps2.GetCodeSize(expectedContractAddress), 0)
  180. privateStateRepo.Reset()
  181. emptyState, _ = privateStateRepo.DefaultState()
  182. assert.False(t, emptyState.Exist(expectedContractAddress))
  183. assert.Equal(t, emptyState.GetCodeSize(expectedContractAddress), 0)
  184. ps1, _ = privateStateRepo.StatePSI(types.PrivateStateIdentifier("psi1"))
  185. assert.False(t, ps1.Exist(expectedContractAddress))
  186. assert.Equal(t, ps1.GetCodeSize(expectedContractAddress), 0)
  187. ps2, _ = privateStateRepo.StatePSI(types.PrivateStateIdentifier("psi2"))
  188. assert.False(t, ps2.Exist(expectedContractAddress))
  189. assert.Equal(t, ps2.GetCodeSize(expectedContractAddress), 0)
  190. }
  191. }
  192. }
  193. func TestPrivateStateMetadataResolver(t *testing.T) {
  194. mockCtrl := gomock.NewController(t)
  195. defer mockCtrl.Finish()
  196. mockptm := private.NewMockPrivateTransactionManager(mockCtrl)
  197. saved := private.P
  198. defer func() {
  199. private.P = saved
  200. }()
  201. private.P = mockptm
  202. mockptm.EXPECT().Receive(gomock.Not(common.EncryptedPayloadHash{})).Return("", []string{"AAA", "CCC"}, common.FromHex(testCode), nil, nil).AnyTimes()
  203. mockptm.EXPECT().Receive(common.EncryptedPayloadHash{}).Return("", []string{}, common.EncryptedPayloadHash{}.Bytes(), nil, nil).AnyTimes()
  204. mockptm.EXPECT().HasFeature(engine.MultiplePrivateStates).Return(true)
  205. mockptm.EXPECT().Groups().Return(PrivacyGroups, nil).AnyTimes()
  206. _, _, blockchain := buildTestChain(1, params.QuorumMPSTestChainConfig)
  207. mpsm := blockchain.privateStateManager
  208. psm1, _ := mpsm.ResolveForManagedParty("AAA")
  209. psm2, _ := mpsm.ResolveForManagedParty("CCC")
  210. _, err := mpsm.ResolveForManagedParty("TEST")
  211. assert.Equal(t, psm1, privacyGroupToPrivateStateMetadata(PG1))
  212. assert.Equal(t, psm2, privacyGroupToPrivateStateMetadata(PG2))
  213. assert.Error(t, err, "unable to find private state metadata for managed party TEST")
  214. ctx := rpc.WithPrivateStateIdentifier(context.Background(), types.ToPrivateStateIdentifier("RG1"))
  215. psm1, _ = mpsm.ResolveForUserContext(ctx)
  216. assert.Equal(t, psm1, privacyGroupToPrivateStateMetadata(PG1))
  217. ctx = rpc.WithPrivateStateIdentifier(context.Background(), types.ToPrivateStateIdentifier("OTHER"))
  218. _, err = mpsm.ResolveForUserContext(ctx)
  219. assert.Error(t, err, "unable to find private state for context psi OTHER")
  220. _, err = mpsm.ResolveForUserContext(context.Background())
  221. assert.Error(t, err, "unable to find private state for context psi private")
  222. assert.Contains(t, mpsm.PSIs(), types.PrivateStateIdentifier("RG1"))
  223. assert.Contains(t, mpsm.PSIs(), types.PrivateStateIdentifier("RG2"))
  224. assert.Contains(t, mpsm.PSIs(), types.PrivateStateIdentifier("LEGACY1"))
  225. }
  226. var PSI1PSM = mps.PrivateStateMetadata{
  227. ID: "psi1",
  228. Name: "psi1",
  229. Description: "private state 1",
  230. Type: mps.Resident,
  231. Addresses: nil,
  232. }
  233. var PSI2PSM = mps.PrivateStateMetadata{
  234. ID: "psi2",
  235. Name: "psi2",
  236. Description: "private state 2",
  237. Type: mps.Resident,
  238. Addresses: nil,
  239. }
  240. var PG1 = engine.PrivacyGroup{
  241. Type: "RESIDENT",
  242. Name: "RG1",
  243. PrivacyGroupId: "RG1",
  244. Description: "Resident Group 1",
  245. From: "",
  246. Members: []string{"AAA", "BBB"},
  247. }
  248. var PG2 = engine.PrivacyGroup{
  249. Type: "RESIDENT",
  250. Name: "RG2",
  251. PrivacyGroupId: "RG2",
  252. Description: "Resident Group 2",
  253. From: "",
  254. Members: []string{"CCC", "DDD"},
  255. }
  256. var PrivacyGroups = []engine.PrivacyGroup{
  257. {
  258. Type: "RESIDENT",
  259. Name: "RG1",
  260. PrivacyGroupId: base64.StdEncoding.EncodeToString([]byte("RG1")),
  261. Description: "Resident Group 1",
  262. From: "",
  263. Members: []string{"AAA", "BBB"},
  264. },
  265. {
  266. Type: "RESIDENT",
  267. Name: "RG2",
  268. PrivacyGroupId: base64.StdEncoding.EncodeToString([]byte("RG2")),
  269. Description: "Resident Group 2",
  270. From: "",
  271. Members: []string{"CCC", "DDD"},
  272. },
  273. {
  274. Type: "LEGACY",
  275. Name: "LEGACY1",
  276. PrivacyGroupId: "LEGACY1",
  277. Description: "Legacy Group 1",
  278. From: "",
  279. Members: []string{"LEG1", "LEG2"},
  280. },
  281. }