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?