evm_privacy_test.go 15 KB

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