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