Skip to content

Commit

Permalink
clean up storage and account tombstones from BlockCache when account …
Browse files Browse the repository at this point in the history
…removal has occurred, for example after SELFDESTRUCT
  • Loading branch information
Silas Davis committed May 8, 2017
1 parent 7454c0a commit 288737d
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 1 deletion.
11 changes: 10 additions & 1 deletion manager/burrow-mint/state/block_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ func (cache *BlockCache) Sync() {
curStorage = storage
}
if curAccRemoved {
// We should delete any storage for removed accounts in anticipation of
// those accounts being reaped from the cache
delete(cache.storages, storageKey)
continue
}
value, dirty := cache.storages[storageKey].unpack()
Expand Down Expand Up @@ -224,8 +227,12 @@ func (cache *BlockCache) Sync() {
if removed {
removed := cache.backend.RemoveAccount([]byte(addrStr))
if !removed {
sanity.PanicCrisis(fmt.Sprintf("Could not remove account to be removed: %X", acc.Address))
sanity.PanicCrisis(fmt.Sprintf("Could not remove account to be removed: %X", addrStr))
}
// Since attempting to delete an already deleted account leads to a
// PanicCrisis (above) we must make sure we remove the tombstones of
// removed accounts
delete(cache.accounts, addrStr)
} else {
if acc == nil {
continue
Expand Down Expand Up @@ -259,6 +266,8 @@ func (cache *BlockCache) Sync() {
if !removed {
sanity.PanicCrisis(fmt.Sprintf("Could not remove namereg entry to be removed: %s", nameStr))
}
// Remove the tombstone name reg object from the cache
delete(cache.names, nameStr)
} else {
if entry == nil {
continue
Expand Down
103 changes: 103 additions & 0 deletions manager/burrow-mint/state/block_cache_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package state

import (
"testing"

"fmt"

"github.com/hyperledger/burrow/account"
"github.com/hyperledger/burrow/core/types"
"github.com/hyperledger/burrow/genesis"
ptypes "github.com/hyperledger/burrow/permission/types"
"github.com/stretchr/testify/assert"
"github.com/tendermint/go-db"
)

func TestBlockCache_Sync_Accounts(t *testing.T) {
blockCache := NewBlockCache(stateForBlockCache(t, 10))
blockCache.RemoveAccount(accountAddress(1))
blockCache.Sync()
// Expect account cache objects to be reaped so that an attempt is not made
// to remove them twice from merkle tree
defer func() {
if r := recover(); r != nil {
t.Fatalf("Consecutive calls to BlockCache.Sync() failed. " +
"Is cache dirty?\n Error: %s", r)
}
}()
blockCache.Sync()
}

func TestBlockCache_Sync_NameReg(t *testing.T) {
blockCache := NewBlockCache(stateForBlockCache(t, 10))
blockCache.RemoveAccount(accountAddress(1))
nameRegName := "foobs"
nameRegEntry := &types.NameRegEntry{
Name: nameRegName,
Owner: accountAddress(1),
Data: "Dates",
Expires: 434,
}
blockCache.UpdateNameRegEntry(nameRegEntry)
blockCache.Sync()
blockCache.RemoveNameRegEntry(nameRegName)
// Expect name reg cache objects to be reaped so that an attempt is not made
// to remove them twice from merkle tree
blockCache.Sync()
defer func() {
if r := recover(); r != nil {
t.Fatalf("Consecutive calls to BlockCache.Sync() failed. " +
"Is cache dirty?\n Error: %s", r)
}
}()
blockCache.Sync()
}

func stateForBlockCache(t *testing.T, numAccounts byte) *State {
genAccounts := make([]*genesis.GenesisAccount, numAccounts)
genValidators := make([]*genesis.GenesisValidator, 1)
for i := byte(0); i < numAccounts; i++ {
genAccounts[i] = genesisAccount("account", i)
}
genValidators[0] = genesisValidator("validator", 0)
genDoc, err := genesis.MakeGenesisDocFromAccounts("BlockChainTest",
genAccounts, genValidators)
assert.NoError(t, err)
return MakeGenesisState(db.NewMemDB(), &genDoc)
}

func genesisAccount(prefix string, index byte) *genesis.GenesisAccount {
address := accountAddress(index)
return &genesis.GenesisAccount{
Address: address,
Amount: 10000 + int64(index),
Name: accountName(prefix, index, address),
Permissions: &ptypes.DefaultAccountPermissions,
}
}

func genesisValidator(prefix string, index byte) *genesis.GenesisValidator {
privAccount := account.GenPrivAccountFromSecret(
fmt.Sprintf("%s_%v", prefix, index))
return &genesis.GenesisValidator{
PubKey: privAccount.PubKey,
Amount: 1000000 + int64(index),
Name: accountName(prefix, index, privAccount.Address),
UnbondTo: []genesis.BasicAccount{
{
Address: privAccount.Address,
Amount: 100,
},
},
}
}

func accountName(prefix string, index byte, address []byte) string {
return fmt.Sprintf("%s-%v_%X", prefix, index, address)
}

func accountAddress(index byte) []byte {
var address [20]byte
address[19] = index
return address[:]
}

0 comments on commit 288737d

Please sign in to comment.