github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+incompatible/HACKING.md (about) 1 # Hacking on Quorum / various notes 2 3 ## How does private state work? 4 5 Let's look at the EVM structure: 6 7 ```go 8 type EVM struct { 9 ... 10 // StateDB gives access to the underlying state 11 StateDB StateDB 12 // Depth is the current call stack 13 depth int 14 ... 15 16 publicState PublicState 17 privateState PrivateState 18 states [1027]*state.StateDB 19 currentStateDepth uint 20 readOnly bool 21 readOnlyDepth uint 22 } 23 ``` 24 25 The vanilla EVM has a call depth limit of 1024. Our `states` parallel the EVM call stack, recording as contracts in the public and private state call back and forth to each other. Note it doesn't have to be a "public -> private -> public -> private" back-and-forth chain. It can be any sequence of { public, private }. 26 27 The interface for calling is this `Push` / `Pop` sequence: 28 29 ```go 30 evm.Push(getDualState(evm, addr)) 31 defer func() { evm.Pop() }() 32 // ... do work in the pushed state 33 ``` 34 35 The definitions of `Push` and `Pop` are simple and important enough to duplicate here: 36 37 ```go 38 func (env *EVM) Push(statedb StateDB) { 39 if env.privateState != statedb { 40 env.readOnly = true 41 env.readOnlyDepth = env.currentStateDepth 42 } 43 44 if castedStateDb, ok := statedb.(*state.StateDB); ok { 45 env.states[env.currentStateDepth] = castedStateDb 46 env.currentStateDepth++ 47 } 48 49 env.StateDB = statedb 50 } 51 func (env *EVM) Pop() { 52 env.currentStateDepth-- 53 if env.readOnly && env.currentStateDepth == env.readOnlyDepth { 54 env.readOnly = false 55 } 56 env.StateDB = env.states[env.currentStateDepth-1] 57 } 58 ``` 59 60 Note the invariant that `StateDB` always points to the current state db. 61 62 The other interesting note is read only mode. Any time we call from the private state into the public state (`env.privateState != statedb`), we require anything deeper to be *read only*. Private state transactions can't affect public state, so we throw an EVM exception on any mutating operation (`SELFDESTRUCT, CREATE, SSTORE, LOG0, LOG1, LOG2, LOG3, LOG4`). Question: have any more mutating operations been added? Question: could we not mutate deeper private state?