|
|
|
@ -162,57 +162,10 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) { |
|
|
|
|
defer func(memcap uint64) { aggregatorMemoryLimit = memcap }(aggregatorMemoryLimit) |
|
|
|
|
aggregatorMemoryLimit = 0 |
|
|
|
|
|
|
|
|
|
if err := snaps.Cap(common.HexToHash("0x03"), 2); err != nil { |
|
|
|
|
t.Fatalf("failed to merge diff layer onto disk: %v", err) |
|
|
|
|
} |
|
|
|
|
// Since the base layer was modified, ensure that data retrievald on the external reference fail
|
|
|
|
|
if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { |
|
|
|
|
t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) |
|
|
|
|
} |
|
|
|
|
if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale { |
|
|
|
|
t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err) |
|
|
|
|
} |
|
|
|
|
if n := len(snaps.layers); n != 2 { |
|
|
|
|
t.Errorf("post-cap layer count mismatch: have %d, want %d", n, 2) |
|
|
|
|
fmt.Println(snaps.layers) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that if a diff layer becomes stale, no active external references will
|
|
|
|
|
// be returned with junk data. This version of the test flattens every diff layer
|
|
|
|
|
// to check internal corner case around the bottom-most memory accumulator.
|
|
|
|
|
func TestDiffLayerExternalInvalidationFullFlatten(t *testing.T) { |
|
|
|
|
// Create an empty base layer and a snapshot tree out of it
|
|
|
|
|
base := &diskLayer{ |
|
|
|
|
diskdb: rawdb.NewMemoryDatabase(), |
|
|
|
|
root: common.HexToHash("0x01"), |
|
|
|
|
cache: fastcache.New(1024 * 500), |
|
|
|
|
} |
|
|
|
|
snaps := &Tree{ |
|
|
|
|
layers: map[common.Hash]snapshot{ |
|
|
|
|
base.root: base, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
// Commit two diffs on top and retrieve a reference to the bottommost
|
|
|
|
|
accounts := map[common.Hash][]byte{ |
|
|
|
|
common.HexToHash("0xa1"): randomAccount(), |
|
|
|
|
} |
|
|
|
|
if err := snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil); err != nil { |
|
|
|
|
t.Fatalf("failed to create a diff layer: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, accounts, nil); err != nil { |
|
|
|
|
t.Fatalf("failed to create a diff layer: %v", err) |
|
|
|
|
} |
|
|
|
|
if n := len(snaps.layers); n != 3 { |
|
|
|
|
t.Errorf("pre-cap layer count mismatch: have %d, want %d", n, 3) |
|
|
|
|
} |
|
|
|
|
ref := snaps.Snapshot(common.HexToHash("0x02")) |
|
|
|
|
|
|
|
|
|
// Flatten the diff layer into the bottom accumulator
|
|
|
|
|
if err := snaps.Cap(common.HexToHash("0x03"), 1); err != nil { |
|
|
|
|
t.Fatalf("failed to flatten diff layer into accumulator: %v", err) |
|
|
|
|
t.Fatalf("failed to merge accumulator onto disk: %v", err) |
|
|
|
|
} |
|
|
|
|
// Since the accumulator diff layer was modified, ensure that data retrievald on the external reference fail
|
|
|
|
|
// Since the base layer was modified, ensure that data retrievald on the external reference fail
|
|
|
|
|
if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { |
|
|
|
|
t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) |
|
|
|
|
} |
|
|
|
@ -267,7 +220,7 @@ func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) { |
|
|
|
|
t.Errorf("layers modified, got %d exp %d", got, exp) |
|
|
|
|
} |
|
|
|
|
// Flatten the diff layer into the bottom accumulator
|
|
|
|
|
if err := snaps.Cap(common.HexToHash("0x04"), 2); err != nil { |
|
|
|
|
if err := snaps.Cap(common.HexToHash("0x04"), 1); err != nil { |
|
|
|
|
t.Fatalf("failed to flatten diff layer into accumulator: %v", err) |
|
|
|
|
} |
|
|
|
|
// Since the accumulator diff layer was modified, ensure that data retrievald on the external reference fail
|
|
|
|
@ -389,7 +342,7 @@ func TestSnaphots(t *testing.T) { |
|
|
|
|
// Create a starting base layer and a snapshot tree out of it
|
|
|
|
|
base := &diskLayer{ |
|
|
|
|
diskdb: rawdb.NewMemoryDatabase(), |
|
|
|
|
root: common.HexToHash("0x01"), |
|
|
|
|
root: makeRoot(1), |
|
|
|
|
cache: fastcache.New(1024 * 500), |
|
|
|
|
} |
|
|
|
|
snaps := &Tree{ |
|
|
|
@ -397,17 +350,16 @@ func TestSnaphots(t *testing.T) { |
|
|
|
|
base.root: base, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
// Construct the snapshots with 128 layers
|
|
|
|
|
// Construct the snapshots with 129 layers, flattening whatever's above that
|
|
|
|
|
var ( |
|
|
|
|
last = common.HexToHash("0x01") |
|
|
|
|
head common.Hash |
|
|
|
|
) |
|
|
|
|
// Flush another 128 layers, one diff will be flatten into the parent.
|
|
|
|
|
for i := 0; i < 128; i++ { |
|
|
|
|
for i := 0; i < 129; i++ { |
|
|
|
|
head = makeRoot(uint64(i + 2)) |
|
|
|
|
snaps.Update(head, last, nil, setAccount(fmt.Sprintf("%d", i+2)), nil) |
|
|
|
|
last = head |
|
|
|
|
snaps.Cap(head, 128) // 129 layers(128 diffs + 1 disk) are allowed, 129th is the persistent layer
|
|
|
|
|
snaps.Cap(head, 128) // 130 layers (128 diffs + 1 accumulator + 1 disk)
|
|
|
|
|
} |
|
|
|
|
var cases = []struct { |
|
|
|
|
headRoot common.Hash |
|
|
|
@ -417,22 +369,57 @@ func TestSnaphots(t *testing.T) { |
|
|
|
|
expectBottom common.Hash |
|
|
|
|
}{ |
|
|
|
|
{head, 0, false, 0, common.Hash{}}, |
|
|
|
|
{head, 64, false, 64, makeRoot(127 + 2 - 63)}, |
|
|
|
|
{head, 128, false, 128, makeRoot(2)}, // All diff layers
|
|
|
|
|
{head, 129, true, 128, makeRoot(2)}, // All diff layers
|
|
|
|
|
{head, 129, false, 129, common.HexToHash("0x01")}, // All diff layers + disk layer
|
|
|
|
|
{head, 64, false, 64, makeRoot(129 + 2 - 64)}, |
|
|
|
|
{head, 128, false, 128, makeRoot(3)}, // Normal diff layers, no accumulator
|
|
|
|
|
{head, 129, true, 129, makeRoot(2)}, // All diff layers, including accumulator
|
|
|
|
|
{head, 130, false, 130, makeRoot(1)}, // All diff layers + disk layer
|
|
|
|
|
} |
|
|
|
|
for i, c := range cases { |
|
|
|
|
layers := snaps.Snapshots(c.headRoot, c.limit, c.nodisk) |
|
|
|
|
if len(layers) != c.expected { |
|
|
|
|
t.Errorf("non-overflow test %d: returned snapshot layers are mismatched, want %v, got %v", i, c.expected, len(layers)) |
|
|
|
|
} |
|
|
|
|
if len(layers) == 0 { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
bottommost := layers[len(layers)-1] |
|
|
|
|
if bottommost.Root() != c.expectBottom { |
|
|
|
|
t.Errorf("non-overflow test %d: snapshot mismatch, want %v, get %v", i, c.expectBottom, bottommost.Root()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Above we've tested the normal capping, which leaves the accumulator live.
|
|
|
|
|
// Test that if the bottommost accumulator diff layer overflows the allowed
|
|
|
|
|
// memory limit, the snapshot tree gets capped to one less layer.
|
|
|
|
|
// Commit the diff layer onto the disk and ensure it's persisted
|
|
|
|
|
defer func(memcap uint64) { aggregatorMemoryLimit = memcap }(aggregatorMemoryLimit) |
|
|
|
|
aggregatorMemoryLimit = 0 |
|
|
|
|
|
|
|
|
|
snaps.Cap(head, 128) // 129 (128 diffs + 1 overflown accumulator + 1 disk)
|
|
|
|
|
|
|
|
|
|
cases = []struct { |
|
|
|
|
headRoot common.Hash |
|
|
|
|
limit int |
|
|
|
|
nodisk bool |
|
|
|
|
expected int |
|
|
|
|
expectBottom common.Hash |
|
|
|
|
}{ |
|
|
|
|
{head, 0, false, 0, common.Hash{}}, |
|
|
|
|
{head, 64, false, 64, makeRoot(129 + 2 - 64)}, |
|
|
|
|
{head, 128, false, 128, makeRoot(3)}, // All diff layers, accumulator was flattened
|
|
|
|
|
{head, 129, true, 128, makeRoot(3)}, // All diff layers, accumulator was flattened
|
|
|
|
|
{head, 130, false, 129, makeRoot(2)}, // All diff layers + disk layer
|
|
|
|
|
} |
|
|
|
|
for _, c := range cases { |
|
|
|
|
for i, c := range cases { |
|
|
|
|
layers := snaps.Snapshots(c.headRoot, c.limit, c.nodisk) |
|
|
|
|
if len(layers) != c.expected { |
|
|
|
|
t.Fatalf("Returned snapshot layers are mismatched, want %v, got %v", c.expected, len(layers)) |
|
|
|
|
t.Errorf("overflow test %d: returned snapshot layers are mismatched, want %v, got %v", i, c.expected, len(layers)) |
|
|
|
|
} |
|
|
|
|
if len(layers) == 0 { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
bottommost := layers[len(layers)-1] |
|
|
|
|
if bottommost.Root() != c.expectBottom { |
|
|
|
|
t.Fatalf("Snapshot mismatch, want %v, get %v", c.expectBottom, bottommost.Root()) |
|
|
|
|
t.Errorf("overflow test %d: snapshot mismatch, want %v, get %v", i, c.expectBottom, bottommost.Root()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|