github.com/RobustRoundRobin/quorum@v20.10.0+incompatible/core/vm/runtime/evm_privacy_test.go (about) 1 package runtime 2 3 import ( 4 "fmt" 5 "math/big" 6 "os" 7 "strings" 8 "testing" 9 10 "github.com/ethereum/go-ethereum/core/rawdb" 11 12 "github.com/ethereum/go-ethereum/private/engine" 13 14 "github.com/ethereum/go-ethereum/core/types" 15 16 "github.com/ethereum/go-ethereum/core" 17 "github.com/ethereum/go-ethereum/core/vm" 18 19 "github.com/ethereum/go-ethereum/log" 20 21 "github.com/ethereum/go-ethereum/common/hexutil" 22 23 "github.com/ethereum/go-ethereum/core/state" 24 25 "github.com/ethereum/go-ethereum/accounts/abi" 26 "github.com/ethereum/go-ethereum/common" 27 testifyassert "github.com/stretchr/testify/assert" 28 ) 29 30 /* 31 The following contracts are used as the samples. Bytecodes are compiled using solc 0.5.4 32 33 import "./C2.sol"; 34 35 contract C1 { 36 37 uint x; 38 39 constructor(uint initVal) public { 40 x = initVal; 41 } 42 43 function set(uint newValue) public returns (uint) { 44 x = newValue; 45 return x; 46 } 47 48 function get() public view returns (uint) { 49 return x; 50 } 51 52 function newContractC2(uint newValue) public { 53 C2 c = new C2(address(this)); 54 c.set(newValue); 55 } 56 } 57 58 import "./C1.sol"; 59 60 contract C2 { 61 62 C1 c1; 63 64 constructor(address _t) public { 65 c1 = C1(_t); 66 } 67 68 function get() public view returns (uint result) { 69 return c1.get(); 70 } 71 72 function set(uint _val) public { 73 c1.set(_val); 74 } 75 76 } 77 */ 78 79 type contract struct { 80 abi abi.ABI 81 bytecode []byte 82 name string 83 } 84 85 var ( 86 c1, c2 *contract 87 stubPrivateTx *types.Transaction 88 ) 89 90 func init() { 91 c1 = &contract{ 92 name: "c1", 93 abi: mustParse(c1AbiDefinition), 94 bytecode: common.Hex2Bytes("608060405234801561001057600080fd5b506040516020806105a88339810180604052602081101561003057600080fd5b81019080805190602001909291905050508060008190555050610550806100586000396000f3fe608060405260043610610051576000357c01000000000000000000000000000000000000000000000000000000009004806360fe47b1146100565780636d4ce63c146100a5578063d7139463146100d0575b600080fd5b34801561006257600080fd5b5061008f6004803603602081101561007957600080fd5b810190808035906020019092919050505061010b565b6040518082815260200191505060405180910390f35b3480156100b157600080fd5b506100ba61011e565b6040518082815260200191505060405180910390f35b3480156100dc57600080fd5b50610109600480360360208110156100f357600080fd5b8101908080359060200190929190505050610127565b005b6000816000819055506000549050919050565b60008054905090565b600030610132610212565b808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050604051809103906000f080158015610184573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff166360fe47b1836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b1580156101f657600080fd5b505af115801561020a573d6000803e3d6000fd5b505050505050565b604051610302806102238339019056fe608060405234801561001057600080fd5b506040516020806103028339810180604052602081101561003057600080fd5b8101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610271806100916000396000f3fe608060405260043610610046576000357c01000000000000000000000000000000000000000000000000000000009004806360fe47b11461004b5780636d4ce63c14610086575b600080fd5b34801561005757600080fd5b506100846004803603602081101561006e57600080fd5b81019080803590602001909291905050506100b1565b005b34801561009257600080fd5b5061009b610180565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166360fe47b1826040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561014157600080fd5b505af1158015610155573d6000803e3d6000fd5b505050506040513d602081101561016b57600080fd5b81019080805190602001909291905050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636d4ce63c6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b15801561020557600080fd5b505afa158015610219573d6000803e3d6000fd5b505050506040513d602081101561022f57600080fd5b810190808051906020019092919050505090509056fea165627a7a72305820a537f4c360ce5c6f55523298e314e6456e5c3e02c170563751dfda37d3aeddb30029a165627a7a7230582060396bfff29d2dfc5a9f4216bfba5e24d031d54fd4b26ebebde1a26c59df0c1e0029"), 95 } 96 c2 = &contract{ 97 name: "c2", 98 abi: mustParse(c2AbiDefinition), 99 bytecode: common.Hex2Bytes("608060405234801561001057600080fd5b506040516020806102f58339810180604052602081101561003057600080fd5b8101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610264806100916000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c01000000000000000000000000000000000000000000000000000000009004806360fe47b1146100585780636d4ce63c14610086575b600080fd5b6100846004803603602081101561006e57600080fd5b81019080803590602001909291905050506100a4565b005b61008e610173565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166360fe47b1826040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561013457600080fd5b505af1158015610148573d6000803e3d6000fd5b505050506040513d602081101561015e57600080fd5b81019080805190602001909291905050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636d4ce63c6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156101f857600080fd5b505afa15801561020c573d6000803e3d6000fd5b505050506040513d602081101561022257600080fd5b810190808051906020019092919050505090509056fea165627a7a72305820dd8a5dcf693e1969289c444a282d0684a9760bac26f1e4e0139d46821ec1979b0029"), 100 } 101 log.PrintOrigins(true) 102 log.Root().SetHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(true))) 103 } 104 105 func TestPrivacyEnhancements_CreateC1(t *testing.T) { 106 assert := testifyassert.New(t) 107 cfg := newConfig() 108 initialValue := int64(42) 109 var affectedContracts []common.Address 110 var getPrivacyMetadataFunc func(common.Address) (*state.PrivacyMetadata, error) 111 cfg.onAfterEVM = func(evm *vm.EVM) { 112 affectedContracts = evm.AffectedContracts() 113 getPrivacyMetadataFunc = evm.StateDB.GetStatePrivacyMetadata 114 } 115 stubPrivateTx = newTypicalPrivateTx(cfg) 116 stubPrivateTx.SetTxPrivacyMetadata(&types.PrivacyMetadata{ 117 PrivacyFlag: engine.PrivacyFlagStateValidation, 118 }) 119 120 c1Address := createC1(assert, cfg, initialValue) 121 assert.Empty(affectedContracts, "Contract C1 creation doesn't affect any other contract") 122 pm, err := getPrivacyMetadataFunc(c1Address) 123 assert.NoError(err, "Privacy Metadata must exist") 124 assert.True(pm.PrivacyFlag.Has(engine.PrivacyFlagStateValidation), "PrivacyFlag must be set") 125 assert.Equal(common.BytesToEncryptedPayloadHash(stubPrivateTx.Data()), pm.CreationTxHash, "CreationTxHash must be set correctly") 126 127 actualValue := callContractFunction(assert, cfg, c1, c1Address, "get") 128 assert.Equal(initialValue, actualValue) 129 assert.Len(affectedContracts, 1, "Calling C1.get() affects 1 contract") 130 assert.Equal(c1Address, affectedContracts[0], "Calling C1.get() affects C1 contract itself") 131 } 132 133 func TestPrivacyEnhancements_CreateC2(t *testing.T) { 134 assert := testifyassert.New(t) 135 cfg := newConfig() 136 stubPrivateTx = nil 137 initialValue := int64(30) 138 139 c1Address := createC1(assert, cfg, initialValue) 140 141 var affectedContracts []common.Address 142 cfg.onAfterEVM = func(evm *vm.EVM) { 143 affectedContracts = evm.AffectedContracts() 144 } 145 c2Address := createC2(assert, cfg, c1Address) 146 assert.Empty(affectedContracts, "Contract C2 creation doesn't affect any other contract") 147 148 actualValue := callContractFunction(assert, cfg, c2, c2Address, "get") 149 150 assert.Equal(initialValue, actualValue) 151 assert.Len(affectedContracts, 2, "Calling C2.get() affects 2 contracts") 152 assert.Contains(affectedContracts, c1Address, "Calling C2.get() affects C1") 153 assert.Contains(affectedContracts, c2Address, "Calling C2.get() affects C2") 154 } 155 156 func TestPrivacyEnhancements_CreateC2FromC1Function(t *testing.T) { 157 assert := testifyassert.New(t) 158 cfg := newConfig() 159 stubPrivateTx = nil 160 initialValue := int64(30) 161 newValue := int64(40) 162 163 c1Address := createC1(assert, cfg, initialValue) 164 165 var affectedContracts []common.Address 166 cfg.onAfterEVM = func(evm *vm.EVM) { 167 affectedContracts = evm.AffectedContracts() 168 } 169 callContractFunction(assert, cfg, c1, c1Address, "newContractC2", big.NewInt(newValue)) 170 171 assert.Len(affectedContracts, 1, "Calling C1.newContractC2() affects 1 contract") 172 assert.Contains(affectedContracts, c1Address, "Calling C1.newContractC2() affects C1") 173 } 174 175 func TestPrivacyEnhancements_CreateC1_StandardPrivate(t *testing.T) { 176 assert := testifyassert.New(t) 177 cfg := newConfig() 178 initialValue := int64(42) 179 var affectedContracts []common.Address 180 var getPrivacyMetadataFunc func(common.Address) (*state.PrivacyMetadata, error) 181 cfg.onAfterEVM = func(evm *vm.EVM) { 182 affectedContracts = evm.AffectedContracts() 183 getPrivacyMetadataFunc = evm.StateDB.GetStatePrivacyMetadata 184 } 185 stubPrivateTx = newTypicalPrivateTx(cfg) 186 stubPrivateTx.SetTxPrivacyMetadata(&types.PrivacyMetadata{ 187 PrivacyFlag: engine.PrivacyFlagStandardPrivate, 188 }) 189 190 c1Address := createC1(assert, cfg, initialValue) 191 assert.Empty(affectedContracts, "Contract C1 creation doesn't affect any other contract") 192 _, err := getPrivacyMetadataFunc(c1Address) 193 assert.Error(err, "Privacy Metadata must not exist") 194 195 actualValue := callContractFunction(assert, cfg, c1, c1Address, "get") 196 assert.Equal(initialValue, actualValue) 197 assert.Len(affectedContracts, 1, "Calling C1.get() affects 1 contract") 198 assert.Equal(c1Address, affectedContracts[0], "Calling C1.get() affects C1 contract itself") 199 } 200 201 func callContractFunction(assert *testifyassert.Assertions, cfg *extendedConfig, c *contract, address common.Address, name string, args ...interface{}) int64 { 202 f := mustPack(assert, c, name, args...) 203 ret, _, err := call(address, f, cfg) 204 sig := fmt.Sprintf("%s.%s", c.name, name) 205 assert.NoError(err, "Execute %s", sig) 206 log.Debug(sig, "ret_hex", common.Bytes2Hex(ret)) 207 for len(ret) > 0 && ret[0] == 0 { 208 ret = ret[1:] 209 } 210 if len(ret) == 0 { 211 return -1 212 } 213 actualValue, err := hexutil.DecodeBig(hexutil.Encode(ret)) 214 assert.NoError(err) 215 log.Debug(sig, "ret", actualValue) 216 return actualValue.Int64() 217 } 218 219 func createC2(assert *testifyassert.Assertions, cfg *extendedConfig, c1Address common.Address) common.Address { 220 constructorCode := mustPack(assert, c2, "", c1Address) 221 222 _, address, _, err := create(append(c2.bytecode, constructorCode...), cfg) 223 assert.NoError(err, "Create contract C2") 224 225 log.Debug("Created C2", "address", address.Hex()) 226 return address 227 } 228 229 func createC1(assert *testifyassert.Assertions, cfg *extendedConfig, initialValue int64) common.Address { 230 constructorCode := mustPack(assert, c1, "", big.NewInt(initialValue)) 231 232 _, address, _, err := create(append(c1.bytecode, constructorCode...), cfg) 233 assert.NoError(err, "Create contract C1") 234 235 log.Debug("Created C1", "address", address.Hex()) 236 return address 237 } 238 239 func mustPack(assert *testifyassert.Assertions, c *contract, name string, args ...interface{}) []byte { 240 bytes, err := c.abi.Pack(name, args...) 241 assert.NoError(err, "Pack method") 242 return bytes 243 } 244 245 func newConfig() *extendedConfig { 246 cfg := new(Config) 247 setDefaults(cfg) 248 cfg.Debug = true 249 database := rawdb.NewMemoryDatabase() 250 cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(database)) 251 privateState, _ := state.New(common.Hash{}, state.NewDatabase(database)) 252 253 cfg.ChainConfig.IsQuorum = true 254 cfg.ChainConfig.ByzantiumBlock = big.NewInt(0) 255 return &extendedConfig{ 256 Config: cfg, 257 privateState: privateState, 258 } 259 } 260 261 type extendedConfig struct { 262 *Config 263 privateState *state.StateDB 264 onAfterEVM func(evm *vm.EVM) 265 } 266 267 func newEVM(cfg *extendedConfig) *vm.EVM { 268 context := vm.Context{ 269 CanTransfer: core.CanTransfer, 270 Transfer: core.Transfer, 271 GetHash: func(uint64) common.Hash { return common.Hash{} }, 272 273 Origin: cfg.Origin, 274 Coinbase: cfg.Coinbase, 275 BlockNumber: cfg.BlockNumber, 276 Time: cfg.Time, 277 Difficulty: cfg.Difficulty, 278 GasLimit: cfg.GasLimit, 279 GasPrice: cfg.GasPrice, 280 } 281 evm := vm.NewEVM(context, cfg.State, cfg.privateState, cfg.ChainConfig, cfg.EVMConfig) 282 evm.SetCurrentTX(stubPrivateTx) 283 return evm 284 } 285 286 func newTypicalPrivateTx(cfg *extendedConfig) *types.Transaction { 287 tx := types.NewTransaction(0, common.Address{}, cfg.Value, cfg.GasLimit, cfg.GasPrice, []byte("arbitrary payload")) 288 tx.SetPrivate() 289 return tx 290 } 291 292 // Create executes the code using the EVM create method 293 func create(input []byte, cfg *extendedConfig) ([]byte, common.Address, uint64, error) { 294 var ( 295 vmenv = newEVM(cfg) 296 sender = vm.AccountRef(cfg.Origin) 297 ) 298 defer func() { 299 if cfg.onAfterEVM != nil { 300 cfg.onAfterEVM(vmenv) 301 } 302 }() 303 304 // Call the code with the given configuration. 305 code, address, leftOverGas, err := vmenv.Create( 306 sender, 307 input, 308 cfg.GasLimit, 309 cfg.Value, 310 ) 311 return code, address, leftOverGas, err 312 } 313 314 // Call executes the code given by the contract's address. It will return the 315 // EVM's return value or an error if it failed. 316 // 317 // Call, unlike Execute, requires a config and also requires the State field to 318 // be set. 319 func call(address common.Address, input []byte, cfg *extendedConfig) ([]byte, uint64, error) { 320 vmenv := newEVM(cfg) 321 defer func() { 322 if cfg.onAfterEVM != nil { 323 cfg.onAfterEVM(vmenv) 324 } 325 }() 326 327 sender := cfg.State.GetOrNewStateObject(cfg.Origin) 328 // Call the code with the given configuration. 329 ret, leftOverGas, err := vmenv.Call( 330 sender, 331 address, 332 input, 333 cfg.GasLimit, 334 cfg.Value, 335 ) 336 337 return ret, leftOverGas, err 338 } 339 340 func mustParse(def string) abi.ABI { 341 abi, err := abi.JSON(strings.NewReader(def)) 342 if err != nil { 343 log.Error("Can't parse ABI def", "err", err) 344 os.Exit(1) 345 } 346 return abi 347 } 348 349 const ( 350 c1AbiDefinition = ` 351 [ 352 { 353 "constant": false, 354 "inputs": [ 355 { 356 "name": "newValue", 357 "type": "uint256" 358 } 359 ], 360 "name": "set", 361 "outputs": [ 362 { 363 "name": "", 364 "type": "uint256" 365 } 366 ], 367 "payable": false, 368 "stateMutability": "nonpayable", 369 "type": "function" 370 }, 371 { 372 "constant": true, 373 "inputs": [], 374 "name": "get", 375 "outputs": [ 376 { 377 "name": "", 378 "type": "uint256" 379 } 380 ], 381 "payable": false, 382 "stateMutability": "view", 383 "type": "function" 384 }, 385 { 386 "constant": false, 387 "inputs": [ 388 { 389 "name": "newValue", 390 "type": "uint256" 391 } 392 ], 393 "name": "newContractC2", 394 "outputs": [], 395 "payable": false, 396 "stateMutability": "nonpayable", 397 "type": "function" 398 }, 399 { 400 "inputs": [ 401 { 402 "name": "initVal", 403 "type": "uint256" 404 } 405 ], 406 "payable": false, 407 "stateMutability": "nonpayable", 408 "type": "constructor" 409 } 410 ] 411 ` 412 c2AbiDefinition = ` 413 [ 414 { 415 "constant": false, 416 "inputs": [ 417 { 418 "name": "_val", 419 "type": "uint256" 420 } 421 ], 422 "name": "set", 423 "outputs": [], 424 "payable": false, 425 "stateMutability": "nonpayable", 426 "type": "function" 427 }, 428 { 429 "constant": true, 430 "inputs": [], 431 "name": "get", 432 "outputs": [ 433 { 434 "name": "result", 435 "type": "uint256" 436 } 437 ], 438 "payable": false, 439 "stateMutability": "view", 440 "type": "function" 441 }, 442 { 443 "inputs": [ 444 { 445 "name": "_t", 446 "type": "address" 447 } 448 ], 449 "payable": false, 450 "stateMutability": "nonpayable", 451 "type": "constructor" 452 } 453 ] 454 ` 455 )