Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix eth_getCode for non-empty accounts without code #1474

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions state/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ const (
TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract
)

var emptyCodeHashTwo = types.BytesToHash(crypto.Keccak256(nil))

// GetHashByNumber returns the hash function of a block number
type GetHashByNumber = func(i uint64) types.Hash

Expand Down Expand Up @@ -795,21 +793,14 @@ func (t *Transition) applyCall(
return result
}

var emptyHash types.Hash

func (t *Transition) hasCodeOrNonce(addr types.Address) bool {
nonce := t.state.GetNonce(addr)
if nonce != 0 {
if t.state.GetNonce(addr) != 0 {
return true
}

codeHash := t.state.GetCodeHash(addr)

if codeHash != emptyCodeHashTwo && codeHash != emptyHash {
return true
}

return false
return codeHash != types.EmptyCodeHash && codeHash != types.ZeroHash
}

func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtime.ExecutionResult {
Expand Down
4 changes: 4 additions & 0 deletions state/immutable-trie/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func (s *State) SetCode(hash types.Hash, code []byte) {
}

func (s *State) GetCode(hash types.Hash) ([]byte, bool) {
if hash == types.EmptyCodeHash {
return []byte{}, true
}

return s.storage.GetCode(hash)
}

Expand Down
3 changes: 1 addition & 2 deletions state/immutable-trie/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ func TestState(t *testing.T) {
func buildPreState(pre state.PreStates) state.Snapshot {
storage := NewMemoryStorage()
st := NewState(storage)
snap := st.NewSnapshot()

return snap
return st.NewSnapshot()
}
7 changes: 3 additions & 4 deletions state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
iradix "github.com/hashicorp/go-immutable-radix"
"github.com/umbracle/fastrlp"

"github.com/0xPolygon/polygon-edge/crypto"
"github.com/0xPolygon/polygon-edge/types"
)

Expand Down Expand Up @@ -102,8 +101,6 @@ func (a *Account) Copy() *Account {
return aa
}

var emptyCodeHash = crypto.Keccak256(nil)

// StateObject is the internal representation of the account
type StateObject struct {
Account *Account
Expand All @@ -119,7 +116,9 @@ type StateObject struct {
}

func (s *StateObject) Empty() bool {
return s.Account.Nonce == 0 && s.Account.Balance.Sign() == 0 && bytes.Equal(s.Account.CodeHash, emptyCodeHash)
return s.Account.Nonce == 0 &&
s.Account.Balance.Sign() == 0 &&
bytes.Equal(s.Account.CodeHash, types.EmptyCodeHash.Bytes())
}

// Copy makes a copy of the state object
Expand Down
88 changes: 65 additions & 23 deletions state/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ import (
"github.com/0xPolygon/polygon-edge/types"
)

var addr1 = types.StringToAddress("1")
var addr2 = types.StringToAddress("2")
var (
addr1 = types.StringToAddress("1")
addr2 = types.StringToAddress("2")

var hash0 = types.StringToHash("0")
var hash1 = types.StringToHash("1")
var hash2 = types.StringToHash("2")
hash0 = types.StringToHash("0")
hash1 = types.StringToHash("1")
hash2 = types.StringToHash("2")

var defaultPreState = map[types.Address]*PreState{
addr1: {
State: map[types.Hash]types.Hash{
hash1: hash1,
defaultPreState = map[types.Address]*PreState{
addr1: {
State: map[types.Hash]types.Hash{
hash1: hash1,
},
},
},
}
}
)

// PreState is the account prestate
type PreState struct {
Expand All @@ -41,66 +43,76 @@ func TestState(t *testing.T, buildPreState buildPreState) {
t.Helper()
t.Parallel()

t.Run("", func(t *testing.T) {
t.Run("write state", func(t *testing.T) {
t.Parallel()

testWriteState(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("write empty state", func(t *testing.T) {
t.Parallel()

testWriteEmptyState(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("update state with empty", func(t *testing.T) {
t.Parallel()

testUpdateStateWithEmpty(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("suicide account in pre-state", func(t *testing.T) {
t.Parallel()

testSuicideAccountInPreState(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("suicide account", func(t *testing.T) {
t.Parallel()

testSuicideAccount(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("suicide account with data", func(t *testing.T) {
t.Parallel()

testSuicideAccountWithData(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("suicide coinbase", func(t *testing.T) {
t.Parallel()

testSuicideCoinbase(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("suicide with intermediate commit", func(t *testing.T) {
t.Parallel()

testSuicideWithIntermediateCommit(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("restart refunds", func(t *testing.T) {
t.Parallel()

testRestartRefunds(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("change pre-state account balance to zero", func(t *testing.T) {
t.Parallel()

testChangePrestateAccountBalanceToZero(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("change account balance to zero", func(t *testing.T) {
t.Parallel()

testChangeAccountBalanceToZero(t, buildPreState)
})
t.Run("", func(t *testing.T) {
t.Run("delete common state root", func(t *testing.T) {
t.Parallel()

testDeleteCommonStateRoot(t, buildPreState)
})
t.Run("get code empty code hash", func(t *testing.T) {
t.Parallel()

testGetCodeEmptyCodeHash(t, buildPreState)
})
t.Run("set and get code", func(t *testing.T) {
t.Parallel()

testSetAndGetCode(t, buildPreState)
})
}

func testDeleteCommonStateRoot(t *testing.T, buildPreState buildPreState) {
Expand Down Expand Up @@ -339,3 +351,33 @@ func testChangeAccountBalanceToZero(t *testing.T, buildPreState buildPreState) {
txn = newTxn(snap)
assert.False(t, txn.Exist(addr1))
}

func testGetCodeEmptyCodeHash(t *testing.T, buildPreState buildPreState) {
t.Helper()

// If empty code hash is passed, it is considered as a valid case,
// and in that case we are not retrieving it from the storage.
snap := buildPreState(nil)

code, ok := snap.GetCode(types.EmptyCodeHash)
assert.True(t, ok)
assert.Empty(t, code)
}

func testSetAndGetCode(t *testing.T, buildPreState buildPreState) {
t.Helper()

testCode := []byte{0x2, 0x4, 0x6, 0x8}
snap := buildPreState(nil)

txn := newTxn(snap)
txn.SetCode(addr1, testCode)

affectedObjs := txn.Commit(true)
snap, _ = snap.Commit(affectedObjs)
assert.Len(t, affectedObjs, 1)

code, ok := snap.GetCode(affectedObjs[0].CodeHash)
assert.True(t, ok)
assert.Equal(t, testCode, code)
}
6 changes: 3 additions & 3 deletions state/txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (txn *Txn) upsertAccount(addr types.Address, create bool, f func(object *St
object = &StateObject{
Account: &Account{
Balance: big.NewInt(0),
CodeHash: emptyCodeHash,
CodeHash: types.EmptyCodeHash.Bytes(),
Root: emptyStateHash,
},
}
Expand Down Expand Up @@ -514,7 +514,7 @@ func newStateObject(txn *Txn) *StateObject {
return &StateObject{
Account: &Account{
Balance: big.NewInt(0),
CodeHash: emptyCodeHash,
CodeHash: types.EmptyCodeHash.Bytes(),
Root: emptyStateHash,
},
}
Expand All @@ -524,7 +524,7 @@ func (txn *Txn) CreateAccount(addr types.Address) {
obj := &StateObject{
Account: &Account{
Balance: big.NewInt(0),
CodeHash: emptyCodeHash,
CodeHash: types.EmptyCodeHash.Bytes(),
Root: emptyStateHash,
},
}
Expand Down
4 changes: 4 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ var (

// EmptyUncleHash is the root when there are no uncles
EmptyUncleHash = StringToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")

// EmptyCodeHash is the root where there is no code.
// Equivalent of: `types.BytesToHash(crypto.Keccak256(nil))`
EmptyCodeHash = StringToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
)

type Hash [HashLength]byte
Expand Down