Skip to content

Commit 951a98b

Browse files
committed
core/state: move state account to core/types + abstracted write account to trie ethereum#23567
1 parent d61a159 commit 951a98b

File tree

11 files changed

+82
-37
lines changed

11 files changed

+82
-37
lines changed

core/state/database.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/XinFinOrg/XDPoSChain/common"
2424
"github.com/XinFinOrg/XDPoSChain/common/lru"
2525
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
26+
"github.com/XinFinOrg/XDPoSChain/core/types"
2627
"github.com/XinFinOrg/XDPoSChain/ethdb"
2728
"github.com/XinFinOrg/XDPoSChain/trie"
2829
)
@@ -69,6 +70,9 @@ type Trie interface {
6970
// trie.MissingNodeError is returned.
7071
TryGet(key []byte) ([]byte, error)
7172

73+
// TryUpdateAccount abstract an account write in the trie.
74+
TryUpdateAccount(key []byte, account *types.StateAccount) error
75+
7276
// TryUpdate associates key with value in the trie. If value has length zero, any
7377
// existing value is deleted from the trie. The value bytes must not be modified
7478
// by the caller while they are stored in the trie. If a node was not found in the

core/state/dump.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222

2323
"github.com/XinFinOrg/XDPoSChain/common"
24+
"github.com/XinFinOrg/XDPoSChain/core/types"
2425
"github.com/XinFinOrg/XDPoSChain/rlp"
2526
"github.com/XinFinOrg/XDPoSChain/trie"
2627
)
@@ -48,7 +49,7 @@ func (s *StateDB) RawDump() Dump {
4849
it := trie.NewIterator(s.trie.NodeIterator(nil))
4950
for it.Next() {
5051
addr := s.trie.GetKey(it.Key)
51-
var data Account
52+
var data types.StateAccount
5253
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
5354
panic(err)
5455
}

core/state/iterator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (it *NodeIterator) step() error {
105105
return nil
106106
}
107107
// Otherwise we've reached an account node, initiate data iteration
108-
var account Account
108+
var account types.StateAccount
109109
if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil {
110110
return err
111111
}

core/state/state_object.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ func (s Storage) Copy() Storage {
6262
// Finally, call CommitTrie to write the modified storage trie into a database.
6363
type stateObject struct {
6464
db *StateDB
65-
address common.Address // address of ethereum account
66-
addrHash common.Hash // hash of ethereum address of the account
67-
data Account // Account data with all mutations applied in the scope of block
65+
address common.Address // address of ethereum account
66+
addrHash common.Hash // hash of ethereum address of the account
67+
data types.StateAccount // Account data with all mutations applied in the scope of block
6868

6969
// DB error.
7070
// State objects are used by the consensus core and VM which are
@@ -107,17 +107,8 @@ func (s *stateObject) empty() bool {
107107
return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes())
108108
}
109109

110-
// Account is the Ethereum consensus representation of accounts.
111-
// These objects are stored in the main account trie.
112-
type Account struct {
113-
Nonce uint64
114-
Balance *big.Int
115-
Root common.Hash // merkle root of the storage trie
116-
CodeHash []byte
117-
}
118-
119110
// newObject creates a state object.
120-
func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *stateObject {
111+
func newObject(db *StateDB, address common.Address, data types.StateAccount, onDirty func(addr common.Address)) *stateObject {
121112
if data.Balance == nil {
122113
data.Balance = new(big.Int)
123114
}
@@ -141,7 +132,7 @@ func newObject(db *StateDB, address common.Address, data Account, onDirty func(a
141132

142133
// EncodeRLP implements rlp.Encoder.
143134
func (s *stateObject) EncodeRLP(w io.Writer) error {
144-
return rlp.Encode(w, s.data)
135+
return rlp.Encode(w, &s.data)
145136
}
146137

147138
// setError remembers the first non-nil error it is called with.

core/state/statedb.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -486,12 +486,9 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
486486

487487
// Encode the account and update the account trie
488488
addr := obj.Address()
489-
490-
data, err := rlp.EncodeToBytes(obj)
491-
if err != nil {
492-
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
489+
if err := s.trie.TryUpdateAccount(addr[:], &obj.data); err != nil {
490+
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
493491
}
494-
s.setError(s.trie.TryUpdate(addr[:], data))
495492
}
496493

497494
// deleteStateObject removes the given object from the state trie.
@@ -541,13 +538,13 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
541538
s.setError(err)
542539
return nil
543540
}
544-
var data Account
545-
if err := rlp.DecodeBytes(enc, &data); err != nil {
541+
data := new(types.StateAccount)
542+
if err := rlp.DecodeBytes(enc, data); err != nil {
546543
log.Error("Failed to decode state object", "addr", addr, "err", err)
547544
return nil
548545
}
549546
// Insert into the live set
550-
obj := newObject(s, addr, data, s.MarkStateObjectDirty)
547+
obj := newObject(s, addr, *data, s.MarkStateObjectDirty)
551548
s.setStateObject(obj)
552549
return obj
553550
}
@@ -576,7 +573,7 @@ func (s *StateDB) MarkStateObjectDirty(addr common.Address) {
576573
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
577574
prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that!
578575

579-
newobj = newObject(s, addr, Account{}, s.MarkStateObjectDirty)
576+
newobj = newObject(s, addr, types.StateAccount{}, s.MarkStateObjectDirty)
580577
newobj.setNonce(0) // sets the object to dirty
581578
if prev == nil {
582579
s.journal = append(s.journal, createObjectChange{account: &addr})
@@ -851,7 +848,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
851848
start := time.Now()
852849

853850
root, accountCommitted, err := s.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
854-
var account Account
851+
var account types.StateAccount
855852
if err := rlp.DecodeBytes(leaf, &account); err != nil {
856853
return nil
857854
}

core/state/sync.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"bytes"
2121

2222
"github.com/XinFinOrg/XDPoSChain/common"
23+
"github.com/XinFinOrg/XDPoSChain/core/types"
2324
"github.com/XinFinOrg/XDPoSChain/ethdb"
2425
"github.com/XinFinOrg/XDPoSChain/rlp"
2526
"github.com/XinFinOrg/XDPoSChain/trie"
@@ -43,7 +44,7 @@ func NewStateSync(root common.Hash, database ethdb.KeyValueReader, bloom *trie.S
4344
return err
4445
}
4546
}
46-
var obj Account
47+
var obj types.StateAccount
4748
if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil {
4849
return err
4950
}

core/state/sync_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) {
203203
}
204204
results[len(hashQueue)+i] = trie.SyncResult{Hash: crypto.Keccak256Hash(data), Data: data}
205205
} else {
206-
var acc Account
206+
var acc types.StateAccount
207207
if err := rlp.DecodeBytes(srcTrie.Get(path[0]), &acc); err != nil {
208208
t.Fatalf("failed to decode account on path %x: %v", path, err)
209209
}

core/types/state_account.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2021 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 types
18+
19+
import (
20+
"math/big"
21+
22+
"github.com/XinFinOrg/XDPoSChain/common"
23+
)
24+
25+
// StateAccount is the Ethereum consensus representation of accounts.
26+
// These objects are stored in the main account trie.
27+
type StateAccount struct {
28+
Nonce uint64
29+
Balance *big.Int
30+
Root common.Hash // merkle root of the storage trie
31+
CodeHash []byte
32+
}

trie/secure_trie.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import (
2020
"fmt"
2121

2222
"github.com/XinFinOrg/XDPoSChain/common"
23+
"github.com/XinFinOrg/XDPoSChain/core/types"
2324
"github.com/XinFinOrg/XDPoSChain/log"
25+
"github.com/XinFinOrg/XDPoSChain/rlp"
2426
)
2527

2628
// SecureTrie wraps a trie with key hashing. In a secure trie, all
@@ -85,6 +87,21 @@ func (t *SecureTrie) TryGetNode(path []byte) ([]byte, int, error) {
8587
return t.trie.TryGetNode(path)
8688
}
8789

90+
// TryUpdateAccount will abstract the write of an account to the
91+
// secure trie.
92+
func (t *SecureTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
93+
hk := t.hashKey(key)
94+
data, err := rlp.EncodeToBytes(acc)
95+
if err != nil {
96+
return err
97+
}
98+
if err := t.trie.TryUpdate(hk, data); err != nil {
99+
return err
100+
}
101+
t.getSecKeyCache()[string(hk)] = common.CopyBytes(key)
102+
return nil
103+
}
104+
88105
// Update associates key with value in the trie. Subsequent calls to
89106
// Get will return value. If value has length zero, any existing value
90107
// is deleted from the trie and calls to Get will return nil.

trie/trie.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/XinFinOrg/XDPoSChain/common"
2727
"github.com/XinFinOrg/XDPoSChain/core/types"
2828
"github.com/XinFinOrg/XDPoSChain/log"
29+
"github.com/XinFinOrg/XDPoSChain/rlp"
2930
)
3031

3132
// LeafCallback is a callback type invoked when a trie operation reaches a leaf
@@ -402,6 +403,14 @@ func (t *Trie) Update(key, value []byte) {
402403
}
403404
}
404405

406+
func (t *Trie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
407+
data, err := rlp.EncodeToBytes(acc)
408+
if err != nil {
409+
return fmt.Errorf("can't encode object at %x: %w", key[:], err)
410+
}
411+
return t.TryUpdate(key, data)
412+
}
413+
405414
// TryUpdate associates key with value in the trie. Subsequent calls to
406415
// Get will return value. If value has length zero, any existing value
407416
// is deleted from the trie and calls to Get will return nil.

0 commit comments

Comments
 (0)