Skip to content

Commit

Permalink
Merge pull request #6369 from onflow/gregor/remove-migrations-previewnet
Browse files Browse the repository at this point in the history
[EVM] Legacy migrations removed
  • Loading branch information
ramtinms authored Aug 19, 2024
2 parents d9f7522 + 9fa185f commit 440ebff
Show file tree
Hide file tree
Showing 7 changed files with 14 additions and 786 deletions.
46 changes: 1 addition & 45 deletions fvm/evm/emulator/state/account.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package state

import (
"math/big"

"github.com/holiman/uint256"
gethCommon "github.com/onflow/go-ethereum/common"
gethTypes "github.com/onflow/go-ethereum/core/types"
Expand Down Expand Up @@ -59,47 +57,5 @@ func DecodeAccount(inp []byte) (*Account, error) {
return nil, nil
}
a := &Account{}
// try decoding
err := rlp.DecodeBytes(inp, a)
if err != nil {
// try legacy decoding (fall back)
a = decodeLegacy(inp)
// if no success return the initial error
if a == nil {
return nil, err
}
}
return a, nil

}

// TODO: remove it when the Preview is shut down
// Legacy account type - used big.Int for balances
type accountV0 struct {
// address
Address gethCommon.Address
// balance of the address
Balance *big.Int
// nonce of the address
Nonce uint64
// hash of the code
// if no code the gethTypes.EmptyCodeHash is stored
CodeHash gethCommon.Hash
// the id of the collection holds storage slots for this account
// this value is nil for EOA accounts
CollectionID []byte
}

func decodeLegacy(encoded []byte) *Account {
a0 := &accountV0{}
if err := rlp.DecodeBytes(encoded, a0); err == nil {
return &Account{
Address: a0.Address,
Balance: uint256.MustFromBig(a0.Balance),
Nonce: a0.Nonce,
CodeHash: a0.CodeHash,
CollectionID: a0.CollectionID,
}
}
return nil
return a, rlp.DecodeBytes(inp, a)
}
68 changes: 6 additions & 62 deletions fvm/evm/handler/blockstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const (
BlockHashListCapacity = 256
BlockStoreLatestBlockKey = "LatestBlock"
BlockStoreLatestBlockProposalKey = "LatestBlockProposal"
BlockStoreBlockHashesKey = "LatestBlockHashes"
)

type BlockStore struct {
Expand Down Expand Up @@ -167,75 +166,20 @@ func (bs *BlockStore) BlockHash(height uint64) (gethCommon.Hash, error) {
}

func (bs *BlockStore) getBlockHashList() (*BlockHashList, error) {
// check legacy block hash list first
return bs.checkLegacyAndMigrate()
// TODO: when preview net is out, we can remove the call to legacy and uncomment below
// BlockStoreBlockHashesKey constant also be removed
//
// bhl, err := NewBlockHashList(bs.backend, bs.rootAddress, BlockHashListCapacity)
// if err != nil {
// return nil, err
// }
// if bhl.IsEmpty() {
// err = bhl.Push(
// types.GenesisBlock(bs.chainID).Height,
// types.GenesisBlockHash(bs.chainID),
// )
// if err != nil {
// return nil, err
// }
// }
// return bhl, nil
}

func (bs *BlockStore) checkLegacyAndMigrate() (*BlockHashList, error) {
data, err := bs.backend.GetValue(bs.rootAddress[:], []byte(BlockStoreBlockHashesKey))
if err != nil {
return nil, err
}

// no legacy found
if len(data) == 0 {
bhl, err := NewBlockHashList(bs.backend, bs.rootAddress, BlockHashListCapacity)
if err != nil {
return nil, err
}
if bhl.IsEmpty() {
err = bhl.Push(
types.GenesisBlock(bs.chainID).Height,
types.GenesisBlockHash(bs.chainID),
)
if err != nil {
return nil, err
}
}
return bhl, nil
}

legacy, err := types.NewBlockHashListFromEncoded(data)
if err != nil {
return nil, err
}

// migrate the data
bhl, err := NewBlockHashList(bs.backend, bs.rootAddress, BlockHashListCapacity)
if err != nil {
return nil, err
}
for i := uint64(0); i <= legacy.MaxAvailableHeight(); i++ {
// for the non-existing ones we insert empty hash
_, bh := legacy.BlockHashByHeight(i)
err = bhl.Push(i, bh)

if bhl.IsEmpty() {
err = bhl.Push(
types.GenesisBlock(bs.chainID).Height,
types.GenesisBlockHash(bs.chainID),
)
if err != nil {
return nil, err
}
}

// reset the old key
err = bs.backend.SetValue(bs.rootAddress[:], []byte(BlockStoreBlockHashesKey), nil)
if err != nil {
return nil, err
}

return bhl, nil
}
145 changes: 0 additions & 145 deletions fvm/evm/handler/blockstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

gethCommon "github.com/onflow/go-ethereum/common"
gethRLP "github.com/onflow/go-ethereum/rlp"
"github.com/stretchr/testify/require"

"github.com/onflow/flow-go/fvm/evm/handler"
Expand Down Expand Up @@ -97,147 +96,3 @@ func TestBlockStore(t *testing.T) {
})

}

// TODO: we can remove this when the previewnet is out
func TestBlockStoreMigration(t *testing.T) {
var chainID = flow.Testnet
testutils.RunWithTestBackend(t, func(backend *testutils.TestBackend) {
testutils.RunWithTestFlowEVMRootAddress(t, backend, func(root flow.Address) {
legacyCapacity := 16
maxHeightAdded := 32
legacy := types.NewBlockHashList(16)
for i := 0; i <= maxHeightAdded; i++ {
err := legacy.Push(uint64(i), gethCommon.Hash{byte(i)})
require.NoError(t, err)
}
err := backend.SetValue(
root[:],
[]byte(handler.BlockStoreBlockHashesKey),
legacy.Encode(),
)
require.NoError(t, err)
bs := handler.NewBlockStore(chainID, backend, root)

for i := 0; i <= maxHeightAdded-legacyCapacity; i++ {
h, err := bs.BlockHash(uint64(i))
require.NoError(t, err)
require.Equal(t, gethCommon.Hash{}, h)
}

for i := maxHeightAdded - legacyCapacity + 1; i <= maxHeightAdded; i++ {
h, err := bs.BlockHash(uint64(i))
require.NoError(t, err)
require.Equal(t, gethCommon.Hash{byte(i)}, h)
}
})
})

}

// This test reproduces a state before a breaking change on the Block type,
// which added a timestamp and total gas used,
// then it adds new blocks and makes sure the retrival
// and storage of blocks works as it should, the breaking change was introduced
// in this PR https://github.com/onflow/flow-go/pull/5660
func TestBlockStore_AddedTimestamp(t *testing.T) {
var chainID = flow.Testnet
testutils.RunWithTestBackend(t, func(backend *testutils.TestBackend) {
testutils.RunWithTestFlowEVMRootAddress(t, backend, func(root flow.Address) {

bs := handler.NewBlockStore(chainID, backend, root)

// block type before breaking change (no timestamp and total gas used)
type oldBlockV1 struct {
ParentBlockHash gethCommon.Hash
Height uint64
UUIDIndex uint64
TotalSupply uint64
StateRoot gethCommon.Hash
ReceiptRoot gethCommon.Hash
TransactionHashes []gethCommon.Hash
}

g := types.GenesisBlock(chainID)
h, err := g.Hash()
require.NoError(t, err)

b := oldBlockV1{
ParentBlockHash: h,
Height: 1,
ReceiptRoot: g.ReceiptRoot,
UUIDIndex: 123,
TotalSupply: 1,
StateRoot: h,
TransactionHashes: []gethCommon.Hash{h},
}
blockBytes, err := gethRLP.EncodeToBytes(b)
require.NoError(t, err)

// store a block without timestamp, simulate existing state before the breaking change
err = backend.SetValue(root[:], []byte(handler.BlockStoreLatestBlockKey), blockBytes)
require.NoError(t, err)

block, err := bs.LatestBlock()
require.NoError(t, err)

require.Empty(t, block.Timestamp)
require.Empty(t, block.TotalGasUsed)
require.Equal(t, b.Height, block.Height)
require.Equal(t, b.ParentBlockHash, block.ParentBlockHash)
require.Equal(t, b.ReceiptRoot, block.ReceiptRoot)

// added timestamp
type oldBlockV2 struct {
ParentBlockHash gethCommon.Hash
Height uint64
Timestamp uint64
TotalSupply *big.Int
ReceiptRoot gethCommon.Hash
TransactionHashes []gethCommon.Hash
}

b2 := oldBlockV2{
ParentBlockHash: h,
Height: 2,
TotalSupply: g.TotalSupply,
ReceiptRoot: g.ReceiptRoot,
Timestamp: 1,
}
blockBytes2, err := gethRLP.EncodeToBytes(b2)
require.NoError(t, err)

// store a block without timestamp, simulate existing state before the breaking change
err = backend.SetValue(root[:], []byte(handler.BlockStoreLatestBlockKey), blockBytes2)
require.NoError(t, err)

err = bs.ResetBlockProposal()
require.NoError(t, err)

block2, err := bs.LatestBlock()
require.NoError(t, err)

require.Empty(t, block2.TotalGasUsed)
require.Equal(t, b2.Height, block2.Height)
require.Equal(t, b2.ParentBlockHash, block2.ParentBlockHash)
require.Equal(t, b2.TotalSupply, block2.TotalSupply)
require.Equal(t, b2.ReceiptRoot, block2.ReceiptRoot)
require.Equal(t, b2.Timestamp, block2.Timestamp)

bp, err := bs.BlockProposal()
require.NoError(t, err)

blockBytes3, err := gethRLP.EncodeToBytes(bp.Block)
require.NoError(t, err)

err = backend.SetValue(root[:], []byte(handler.BlockStoreLatestBlockKey), blockBytes3)
require.NoError(t, err)

bb, err := bs.LatestBlock()
require.NoError(t, err)
require.NotNil(t, bb.ParentBlockHash)
require.NotNil(t, bb.TotalGasUsed)
require.NotNil(t, bb.Timestamp)
require.Equal(t, b2.Height+1, bb.Height)
})
})
}
Loading

0 comments on commit 440ebff

Please sign in to comment.