github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/core/state/statedb_test.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package state 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "math" 24 "math/big" 25 "math/rand" 26 "reflect" 27 "strings" 28 "testing" 29 "testing/quick" 30 31 "github.com/atheioschain/go-atheios/common" 32 "github.com/atheioschain/go-atheios/core/types" 33 "github.com/atheioschain/go-atheios/ethdb" 34 ) 35 36 // Tests that updating a state trie does not leak any database writes prior to 37 // actually committing the state. 38 func TestUpdateLeaks(t *testing.T) { 39 // Create an empty state database 40 db, _ := ethdb.NewMemDatabase() 41 state, _ := New(common.Hash{}, db) 42 43 // Update it with some accounts 44 for i := byte(0); i < 255; i++ { 45 addr := common.BytesToAddress([]byte{i}) 46 state.AddBalance(addr, big.NewInt(int64(11*i))) 47 state.SetNonce(addr, uint64(42*i)) 48 if i%2 == 0 { 49 state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) 50 } 51 if i%3 == 0 { 52 state.SetCode(addr, []byte{i, i, i, i, i}) 53 } 54 state.IntermediateRoot(false) 55 } 56 // Ensure that no data was leaked into the database 57 for _, key := range db.Keys() { 58 value, _ := db.Get(key) 59 t.Errorf("State leaked into database: %x -> %x", key, value) 60 } 61 } 62 63 // Tests that no intermediate state of an object is stored into the database, 64 // only the one right before the commit. 65 func TestIntermediateLeaks(t *testing.T) { 66 // Create two state databases, one transitioning to the final state, the other final from the beginning 67 transDb, _ := ethdb.NewMemDatabase() 68 finalDb, _ := ethdb.NewMemDatabase() 69 transState, _ := New(common.Hash{}, transDb) 70 finalState, _ := New(common.Hash{}, finalDb) 71 72 modify := func(state *StateDB, addr common.Address, i, tweak byte) { 73 state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak))) 74 state.SetNonce(addr, uint64(42*i+tweak)) 75 if i%2 == 0 { 76 state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) 77 state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak}) 78 } 79 if i%3 == 0 { 80 state.SetCode(addr, []byte{i, i, i, i, i, tweak}) 81 } 82 } 83 84 // Modify the transient state. 85 for i := byte(0); i < 255; i++ { 86 modify(transState, common.Address{byte(i)}, i, 0) 87 } 88 // Write modifications to trie. 89 transState.IntermediateRoot(false) 90 91 // Overwrite all the data with new values in the transient database. 92 for i := byte(0); i < 255; i++ { 93 modify(transState, common.Address{byte(i)}, i, 99) 94 modify(finalState, common.Address{byte(i)}, i, 99) 95 } 96 97 // Commit and cross check the databases. 98 if _, err := transState.Commit(false); err != nil { 99 t.Fatalf("failed to commit transition state: %v", err) 100 } 101 if _, err := finalState.Commit(false); err != nil { 102 t.Fatalf("failed to commit final state: %v", err) 103 } 104 for _, key := range finalDb.Keys() { 105 if _, err := transDb.Get(key); err != nil { 106 val, _ := finalDb.Get(key) 107 t.Errorf("entry missing from the transition database: %x -> %x", key, val) 108 } 109 } 110 for _, key := range transDb.Keys() { 111 if _, err := finalDb.Get(key); err != nil { 112 val, _ := transDb.Get(key) 113 t.Errorf("extra entry in the transition database: %x -> %x", key, val) 114 } 115 } 116 } 117 118 func TestSnapshotRandom(t *testing.T) { 119 t.Skip("@fjl fix me please") 120 config := &quick.Config{MaxCount: 1000} 121 err := quick.Check((*snapshotTest).run, config) 122 if cerr, ok := err.(*quick.CheckError); ok { 123 test := cerr.In[0].(*snapshotTest) 124 t.Errorf("%v:\n%s", test.err, test) 125 } else if err != nil { 126 t.Error(err) 127 } 128 } 129 130 // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes 131 // captured by the snapshot. Instances of this test with pseudorandom content are created 132 // by Generate. 133 // 134 // The test works as follows: 135 // 136 // A new state is created and all actions are applied to it. Several snapshots are taken 137 // in between actions. The test then reverts each snapshot. For each snapshot the actions 138 // leading up to it are replayed on a fresh, empty state. The behaviour of all public 139 // accessor methods on the reverted state must match the return value of the equivalent 140 // methods on the replayed state. 141 type snapshotTest struct { 142 addrs []common.Address // all account addresses 143 actions []testAction // modifications to the state 144 snapshots []int // actions indexes at which snapshot is taken 145 err error // failure details are reported through this field 146 } 147 148 type testAction struct { 149 name string 150 fn func(testAction, *StateDB) 151 args []int64 152 noAddr bool 153 } 154 155 // newTestAction creates a random action that changes state. 156 func newTestAction(addr common.Address, r *rand.Rand) testAction { 157 actions := []testAction{ 158 { 159 name: "SetBalance", 160 fn: func(a testAction, s *StateDB) { 161 s.SetBalance(addr, big.NewInt(a.args[0])) 162 }, 163 args: make([]int64, 1), 164 }, 165 { 166 name: "AddBalance", 167 fn: func(a testAction, s *StateDB) { 168 s.AddBalance(addr, big.NewInt(a.args[0])) 169 }, 170 args: make([]int64, 1), 171 }, 172 { 173 name: "SetNonce", 174 fn: func(a testAction, s *StateDB) { 175 s.SetNonce(addr, uint64(a.args[0])) 176 }, 177 args: make([]int64, 1), 178 }, 179 { 180 name: "SetState", 181 fn: func(a testAction, s *StateDB) { 182 var key, val common.Hash 183 binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) 184 binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) 185 s.SetState(addr, key, val) 186 }, 187 args: make([]int64, 2), 188 }, 189 { 190 name: "SetCode", 191 fn: func(a testAction, s *StateDB) { 192 code := make([]byte, 16) 193 binary.BigEndian.PutUint64(code, uint64(a.args[0])) 194 binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) 195 s.SetCode(addr, code) 196 }, 197 args: make([]int64, 2), 198 }, 199 { 200 name: "CreateAccount", 201 fn: func(a testAction, s *StateDB) { 202 s.CreateAccount(addr) 203 }, 204 }, 205 { 206 name: "Suicide", 207 fn: func(a testAction, s *StateDB) { 208 s.Suicide(addr) 209 }, 210 }, 211 { 212 name: "AddRefund", 213 fn: func(a testAction, s *StateDB) { 214 s.AddRefund(big.NewInt(a.args[0])) 215 }, 216 args: make([]int64, 1), 217 noAddr: true, 218 }, 219 { 220 name: "AddLog", 221 fn: func(a testAction, s *StateDB) { 222 data := make([]byte, 2) 223 binary.BigEndian.PutUint16(data, uint16(a.args[0])) 224 s.AddLog(&types.Log{Address: addr, Data: data}) 225 }, 226 args: make([]int64, 1), 227 }, 228 } 229 action := actions[r.Intn(len(actions))] 230 var nameargs []string 231 if !action.noAddr { 232 nameargs = append(nameargs, addr.Hex()) 233 } 234 for _, i := range action.args { 235 action.args[i] = rand.Int63n(100) 236 nameargs = append(nameargs, fmt.Sprint(action.args[i])) 237 } 238 action.name += strings.Join(nameargs, ", ") 239 return action 240 } 241 242 // Generate returns a new snapshot test of the given size. All randomness is 243 // derived from r. 244 func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value { 245 // Generate random actions. 246 addrs := make([]common.Address, 50) 247 for i := range addrs { 248 addrs[i][0] = byte(i) 249 } 250 actions := make([]testAction, size) 251 for i := range actions { 252 addr := addrs[r.Intn(len(addrs))] 253 actions[i] = newTestAction(addr, r) 254 } 255 // Generate snapshot indexes. 256 nsnapshots := int(math.Sqrt(float64(size))) 257 if size > 0 && nsnapshots == 0 { 258 nsnapshots = 1 259 } 260 snapshots := make([]int, nsnapshots) 261 snaplen := len(actions) / nsnapshots 262 for i := range snapshots { 263 // Try to place the snapshots some number of actions apart from each other. 264 snapshots[i] = (i * snaplen) + r.Intn(snaplen) 265 } 266 return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil}) 267 } 268 269 func (test *snapshotTest) String() string { 270 out := new(bytes.Buffer) 271 sindex := 0 272 for i, action := range test.actions { 273 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 274 fmt.Fprintf(out, "---- snapshot %d ----\n", sindex) 275 sindex++ 276 } 277 fmt.Fprintf(out, "%4d: %s\n", i, action.name) 278 } 279 return out.String() 280 } 281 282 func (test *snapshotTest) run() bool { 283 // Run all actions and create snapshots. 284 var ( 285 db, _ = ethdb.NewMemDatabase() 286 state, _ = New(common.Hash{}, db) 287 snapshotRevs = make([]int, len(test.snapshots)) 288 sindex = 0 289 ) 290 for i, action := range test.actions { 291 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 292 snapshotRevs[sindex] = state.Snapshot() 293 sindex++ 294 } 295 action.fn(action, state) 296 } 297 298 // Revert all snapshots in reverse order. Each revert must yield a state 299 // that is equivalent to fresh state with all actions up the snapshot applied. 300 for sindex--; sindex >= 0; sindex-- { 301 checkstate, _ := New(common.Hash{}, db) 302 for _, action := range test.actions[:test.snapshots[sindex]] { 303 action.fn(action, checkstate) 304 } 305 state.RevertToSnapshot(snapshotRevs[sindex]) 306 if err := test.checkEqual(state, checkstate); err != nil { 307 test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) 308 return false 309 } 310 } 311 return true 312 } 313 314 // checkEqual checks that methods of state and checkstate return the same values. 315 func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { 316 for _, addr := range test.addrs { 317 var err error 318 checkeq := func(op string, a, b interface{}) bool { 319 if err == nil && !reflect.DeepEqual(a, b) { 320 err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b) 321 return false 322 } 323 return true 324 } 325 // Check basic accessor methods. 326 checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) 327 checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr)) 328 checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) 329 checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) 330 checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) 331 checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) 332 checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) 333 // Check storage. 334 if obj := state.GetStateObject(addr); obj != nil { 335 obj.ForEachStorage(func(key, val common.Hash) bool { 336 return checkeq("GetState("+key.Hex()+")", val, checkstate.GetState(addr, key)) 337 }) 338 checkobj := checkstate.GetStateObject(addr) 339 checkobj.ForEachStorage(func(key, checkval common.Hash) bool { 340 return checkeq("GetState("+key.Hex()+")", state.GetState(addr, key), checkval) 341 }) 342 } 343 if err != nil { 344 return err 345 } 346 } 347 348 if state.GetRefund().Cmp(checkstate.GetRefund()) != 0 { 349 return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", 350 state.GetRefund(), checkstate.GetRefund()) 351 } 352 if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) { 353 return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", 354 state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) 355 } 356 return nil 357 } 358 359 func TestTouchDelete(t *testing.T) { 360 db, _ := ethdb.NewMemDatabase() 361 state, _ := New(common.Hash{}, db) 362 state.GetOrNewStateObject(common.Address{}) 363 root, _ := state.Commit(false) 364 state.Reset(root) 365 366 snapshot := state.Snapshot() 367 state.AddBalance(common.Address{}, new(big.Int)) 368 if len(state.stateObjectsDirty) != 1 { 369 t.Fatal("expected one dirty state object") 370 } 371 372 state.RevertToSnapshot(snapshot) 373 if len(state.stateObjectsDirty) != 0 { 374 t.Fatal("expected no dirty state object") 375 } 376 }